数组
一维数组
二维数组
定义
静态 int array10; 定义了数组,并未初始化
静态 int array10 = { {1,1} , {2,2} }; 数组初始化了array0及array1
指针方式一 : 动态 int (array)[n] = new intm;
delete []array; //n必须为常量
指针方式二 :动态 int array = new int[m];
for(i:m) array[i] = new int[n];
for(i:m) delete []array[i];
delete []array; 多次析构
指针方式三 :动态 int* array = new intm;
delete []array; 数组按行存储
访问
指针形式:如二维数组valuei的访问:
*(value[i] + j) 或
(*(value + i))[j]
多维数组
int* array = new intm[4]; 只有第一维可以是变量,其他维数必须是常量,否则会报错
delete []array; 必须进行内存释放,否则内存将泄漏
数组作为参数
https://blog.csdn.net/gqb_driver/article/details/8886687
字符数组
char array[10] = “cnblogs”;
char array[] = “cnblogs”;
char *array=“cnblogs”;
char filename[100];
数组与指针关系
数组不等于指针
^[数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组;
数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量;
指向数组的指针则是另外一种变量类型,(在win32平台下,长度为4),仅仅意味着数组存放地址。]
内存泄露
我们定义了一个指针,然后给它赋予了一个地址值,然后又不再使用,但是没有delete,那么当给指针赋予其他的地址值时,原来的内存将无法释放,这就叫做内存泄露。
STL 容器
STL中的容器主要是两种:序列式容器和关联式容器。
序列式容器:vector list string等等
关联式容器:set map等
顺序容器
1.顺序容器的特点
顺序容器
vector——可以作为string,cha,int,double等基本类型和自定义类的容器
vec.size() //返回容器的大小
vec.push_back() //在容器尾部插入元素
迭代器——iterator
vector::iterator v = vec.begin();
容器的容器
如vector
Vector中使用结构体Struct
http://www.cnblogs.com/qyaizs/articles/2039101.html
重载结构体‘<’
#include
#include
using namespace std ;
struct Rect
{
int Dir;
int Ini;
int Inj;
};
int main()
{
Rect rect;
vectorvec;
for (int i=0;i<10;i++)
{
rect.Dir=i;
rect.Ini=i+2;
rect.Inj=i*i;
vec.push_back(rect);
}
for (int i=0;i
vector中插入pair
声明 vector
插入 VP.push_back(make_pair
访问 vector
#include
#include
using namespace std;
int main(){
//声明
vector
//插入
VP.push_back(make_pair(10,50));
VP.push_back(make_pair(10,20));
VP.push_back(make_pair(20,40));
VP.push_back(make_pair(40,80));
VP.push_back(make_pair(30,90));
vector > ::iterator iter; //访问vector
iter=VP.begin();
iter++;
iter++;
VP.erase(iter); //删除元素(20,40)
for(iter=VP.begin();iter!=VP.end();iter++)
{
cout<first<<"/t"<second<
}
C++ STL 之 vector 的 capacity 和 size 属性区别
size 是当前 vector 容器真实占用的大小,也就是容器当前拥有多少个容器。
capacity 是指在发生 realloc 前能允许的最大元素数,即预分配的内存空间。
当然,这两个属性分别对应两个方法:resize() 和 reserve()。
使用 resize() 容器内的对象内存空间是真正存在的。
使用 reserve() 仅仅只是修改了 capacity 的值,容器内的对象并没有真实的内存空间(空间是"野"的)。
此时切记使用 [] 操作符访问容器内的对象,很可能出现数组越界的问题。
下面用例子进行说明:
#include
#include
using std::vector;
int main(void)
{
vector v;
std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl;
v.reserve(10);
std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl;
v.resize(10);
v.push_back(0);
std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl;
return 0;
}
运行结果为:(win 10 + VS2010)
注: 对于 reserve(10) 后接着直接使用 [] 访问越界报错(内存是野的),大家可以加一行代码试一下,我这里没有贴出来。
这里直接用[]访问,vector 退化为数组,不会进行越界的判断。此时推荐使用 at(),会先进行越界检查。
相关引申:
针对 capacity 这个属性,STL 中的其他容器,如 list map set deque,由于这些容器的内存是散列分布的,因此不会发生类似 realloc() 的调用情况,因此我们可以认为 capacity 属性针对这些容器是没有意义的,因此设计时这些容器没有该属性。
在 STL 中,拥有 capacity 属性的容器只有 vector 和 string。
数组与vector的互转
https://blog.csdn.net/Sagittarius_Warrior/article/details/54089242
一、数组转vector
float arrHeight[] = { 1.68,1.72,1.83,2.05,2.35,1.78,2.1,1.96 };
vector vecHeight(arrHeight, arrHeight+sizeof(arrHeight)/sizeof(float));
vector转数组
由于vector内部的数据是存放在连续的存储空间,vector转数组事实上只需要获取vector中第一个数据的地址和数据的长度即可。如果仅仅是传参,无需任何操作,直接传地址即可,如果要进行数据复制,可以借用内存拷贝函数“memcpy”。例如:
float *buffer = new float[vecHeight.size()];
if (!vecHeight.empty())
{
memcpy(buffer, &vecHeight[0], vecHeight.size()*sizeof(float));
}
循环删除容器中元素
https://blog.csdn.net/Mrzhoug/article/details/51635361
STL中任何容器都可以使用迭代器进行元素的遍历,当需要在遍历中删除某些元素时,容器中元素的布局(位置或者排序)会随之改变,当前迭代器所指示的元素也会发生变化,这时继续递增或者递减迭代器进行后续元素的遍历时就要特别小心。
https://blog.csdn.net/magictong/article/details/4074381
1、 自己迭代实现删除:
vector::iterator itVec = vectInt.begin();
// 删除所有值为1022的元素
for ( ; itVec != vectInt.end(); )
{
// 删除
if (*itVec == 1022)
itVec = vectInt.erase(itVect);
else
++itVec;
}
list循环删除
list::iterator itList = listInt.begin();
// 删除所有值为1022的元素
for ( ; itList != listInt.end(); )
{
// 删除
if (*itList == 1022)
listInt.erase(itList++);
else
++itList ;
}
3、关联式容器循环删除
for(iter = map.begin(); iter != map.end()?
{
if (shouldDelete(*iter))
map.erase(iter++);
else
++iter;
}
使用stl算法库中的remove remove_if来进行删除:
调用STL中算法 remove或者remove_if的陷阱,并没有真正的删除(你可以此时调用size方法来验证这一点),然后应该使用erase删除残余数据,remove或者remove_if的实现原理是用后面 未被删除的元素 来覆盖前面 应该被删除的元素。返回值ForwardIterator指向经移除后的最后元素的下一位置。如vector{0,1,2,3,3,4},执行remove(),希望移除所有值为3的元素,结果为{0,1,2,4,3,4},返回值ForwardIterator指向第5个元素。即:
0 1 2 3 3 4 移除前
0 1 2 4 3 4 移除后
^[谨慎对待操作STL容器的方法begin end size的优化,常见是将他们提取到循环的外部,如果你执行删除操作,可能导致错误,因为在进行删除操作的时候,容器的end,size很有可能随时变化。list容器的end一直不会变化,但是放在for里面,编译器也会优化。除非你能保证for循环中不会改变容器的大小。
]
pair
pair类型的操作
pair
pair
make_pair(v1,v2); //v1,v2创建一个新的pair对象,其元素类型分别是v1,v2的类型
p1 < p2; //两个pair对象之间的小于运算,其定义遵循字典次序
p1 == p2; //如果两个pair对象的first和second成员依次相等,则两个对象相等
p.first; //p中的first的公有数据成员
p.second; //p中的second的公有数据成员
1)pair的创建和初始化,与顺序容器类似,如下:
pair anon;//调用默认构造函数来初始化
pair word_count;
pair> line;
pair author("jim", "weshon"); //定义时提供初始化
typedef pair Author;
Author product("marcel", "Product");
2)pair对象的操作,支持== 、< ,first、second成员的访问,如下
string firstbook;
if (author.first == "jim" && author.second == "weshon")
{
firstbook = "stephon hero"; //
}
3)生成新的pair对象,如下:
pair next_author;
string first, second;
while (cin >> first >> second)
{
next_author = make_pair(first, second);
//pair next_author(first, second); //与上面创建类似
map
map和multimap的作用,这两种数据类型在存储数据时,会根据pair<>的first成员进行排序,不同的是前者将不会插入对first成员重复的结构,后者可以
map和set不允许为同一个键添加第二个元素,但是还有支持一个键对应多个实例的multimap和multiset类型:
【multimap】支持同一个键多次出现的map类型
【multiset】支持同一个键多次出现的set类型
map的构造函数:
map
map
map
map中键类型的约束,键必须支持“<”操作符,键不允许修改
map
map
map
map word_count;
map> line_count;
map::iterator, int> vcmap;
//map::iterator, int> lsmap; //error, list can't support < operator
map插入数据
第一种:用insert函数插入pair数据
Map
mapStudent.insert(pair
my_Map.insert(make_pair(“d”,4));
2
第二种:用insert函数插入value_type数据
typedef map
Map
mapStudent.insert(map
第三种:用数组方式插入数据
Map
mapStudent[1] = “student_one”;
mapStudent[2] = “student_two”
第四种: 利用迭代器插入
m.insert(beg,end); //beg和end标记元素范围的迭代器,元素类型必须为m.value_type,返回值为void
m.insert(iter,e); //e是一个用在m上的value_type类型的值,不在插入以iter为起点搜索新元素的位置;返回值为一个迭代器指向m中具有给定元素键的元素
string word = "";
while (cin >> word)
{
if (word == "@")
break;
//word_count.insert(map::value_type("Anna", 1));
//word_count.insert(make_pair("Jim", 1));
//typedef map::value_type valType;
//word_count.insert(valType("COM", 1));
pair
查找并读取元素
m.count(k);返回m中k的出现次数
m.find(k);如果m容器中存在按k索引的元素,则返回指向该元素的迭代器;不存在的话,返回超出末端的迭代器
if (word_count.count("jim"))
{
cout << "jim = " << word_count["jim"] << endl;
}
map_iter = word_count.find("tom");
if (map_iter != word_count.end())
{
word_count["tom"] = 250;
cout << "tom = " << map_iter->second << endl;
}
删除元素
m.erase(k); //删除m中关键字为k的元素;返回size_type类型的值,表示删除的元素个数
m.erase§; //删除m中迭代器p指向的元素;p必须存在,且不等于m.end();返回void类型
m.erase(b,e); //删除一段范围内的元素,由迭代器b和e标记;返回为void类型
word_count.erase(“jim”);
map返回值只可能是0或者1,返回0表示不存在
map对象的迭代遍历
map::iterator map_iter = word_count.begin(); //iter: pair 上面已有
map_iter = word_count.begin();
for ( ; map_iter != word_count.end(); ++map_iter)
{
cout << map_iter->first << " " << map_iter->second << endl;
从map中删除元素
m.erase(k),删除 m 中键为 k 的元素。返回 size_type 类型的值,表示删除的元素个数(要么是0,要么是1);
m.erase§ //从 m 中删除迭代器 p 所指向的元素。p 必须指向 m 中确实存在的元素,而且不能等于 m.end()。返回 void
m.erase(b, e),从 m 中删除一段范围内的元素,该范围由迭代器对 b 和 e 标记。b 和 e 必须标记 m 中的一段有效范围:即 b 和 e 都必须指向 m 中的元素或最后一个元素的下一个位置。而且,b 和 e 要么相等(此时删除的范围为空),要么 b 所指向的元素必须出现在 e 所指向的元素之前。返回 void 类型
set
添加元素
set 容器的定义和使用:以一段范围的元素初始化 set 对象,或在 set 对象中插入一组元素时,对于每个键,事实上都只添加了一个元素。
// define a vector with 20 elements, holding two copies of each number from 0 to 9
vector ivec;
for (vector::size_type i = 0; i != 10; ++i) {
ivec.push_back(i);
ivec.push_back(i); // duplicate copies of each number
}
// 对于vector中的重复元素,只插入一个。
set iset(ivec.begin(), ivec.end());
cout << ivec.size() << endl; // prints 20
cout << iset.size() << endl; // prints 10
3
查找元素
set.find()
set.count()
iset.find(1) // returns iterator that refers to the element with key == 1
iset.find(11) // returns iterator == iset.end()
iset.count(1) // returns 1
iset.count(11) // returns 0
删除元素
hashmap介绍
https://blog.csdn.net/q_l_s/article/details/52416583
https://bbs.csdn.net/topics/320066836
数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针,而且在其失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。 ↩︎
m.insert(e); //e是m上的value_type类型,value_type 并非元素的类型,而是描述键及其关联值类型的 pair 类型。如果键不在m中,则插入新元素,在的话,保持m不变;返回值为一个pair类型的对象,包含指向键位e.first的元素的map迭代器以及一个bool类型的对象,表示是否插入了该元素 ↩︎
往set中添加元素:与 map 容器的操作一样,带有一个键参数的 insert 版本返回 pair 类型对象,包含一个迭代器和一个 bool 值,迭代器指向拥有该键的元素,而 bool 值表明是否添加了元素。使用迭代器对的 insert 版本返回 void 类型。 ↩︎