- vector:可变大小的数组,支持随机访问,在尾部之外的位置插入或删除元素可能会很慢;通常,使用vector是最好的选择
- list和forward_list在任何位置插入或删除元素都很快
- 如果要求随机访问元素,应使用vector 或 deque
end可以与begin指向相同的位置,但不能指向begin之前的位置
end指向容器中尾元素之后的位置
类型别名: 通过类型别名,我们可以在不了解容器中元素类型的情况下使用它
list<string> a = {"what", "is", "the", "matter"}; auto it1 = a.begin(); // list<string>::iterator auto it2 = a.rbegin();// r表示返回反向迭代器,list<string>::reverse_iterator auto it3 = a.cbegin();// c表示返回const迭代器,list<string>::const_iterator auto it4 = a.crbegin();// list<string>::const_reverse_iterator可以将普通的iterator转换成const_iterator, 反之不行
-
每个容器类型都定义了一个默认构造函数
-
创建一个容器为另一个容器的拷贝,两个容器的类型及其元素类型必须匹配。不过,当传递迭代器参数来拷贝一个范围时,就不要求容器类型相同
list<string> animals = {"cat", "dog", "pig"}; vector<const char*> ac = {"a", "an", "the"}; list<string> animals_s(animals); forward_list<string> words(ac.begin(), ac.end());
-
列表初始化
vector<int> ievc(10,-1); //10个int元素,每个元素都初始化为 -1 list<string> svec(10,"hi"); //10个string元素,每个都初始化为"hi" forward_list<int> ivec(10); //10个元素,每个都从初始化为 0 deque<string> svec(10); // 10个元素,每个都是空 tring
-
*** 只有顺序容器的构造函数才接受大小参数,关联容器不支持***
-
当定义一个array时,除了定义类型,还要指定大小;一个默认构造的array是非空的
array<int,42> a; array<int, 3> a2 = {1,2,3}; array<int, 3> a3 = {1}; //a3[0]为1,其余元素为0 array<int, 3> a4 = a2; //只要数组类型匹配即合法
-
assign不适用于关联容器和array
list<string> names; vector<const char*> oldstyle; names = oldstyle ; // 错误!因为容器类型不匹配 names.assign(oldstyle.cbegin(), oldstyle.cend()); // 因为oldstyle是const,所以用cbegin()
-
除了array外, swap不对任何元素进行拷贝、删除或插入操作,因此,可以保证在常数时间内完成
-
容器的关系运算,实际上是使用元素的关系运算完成的
-
向一个vector、string或deque插入元素会使所有指向容器的迭代器、引用和指针失效
-
push_back在容器尾部创建新的元素
-
vector和string不支持push_front
-
insert将元素插入到迭代器所指位置之前
vector<string> svec; list<string> slist; // 等同于 slist.push_front("hello"); slidt.insert(slist.begin(),"hello"); svec.insert(svec.begin(),"hello"); svec.insert(svec.end(),10,"action"); // 将10个元素插入到svec的末尾,这些元素都被初始化为”action“ vector<string> color = {"red","blue","yellow"}; // 将color的最后两个元素添加到slist的开始位置 slist.insert(slist.begin(),color.end()-2,color.end()); slist.insert(slist.end(),{"red","blue","green"});
-
每个顺寻容器都有一个front成员函数,除forward_list之外,都有一个back成员函数
// 访问back和front返回的是引用 if (!(c.empty)){ c.front() = 42; // 将 42 赋予c中的第一个元素 auto &v = c.back(); // 获得指向最后一个元素的引用 v = 1024; // 改变c中的元素 auto v2 = c.back(); // v2不是引用,它是 c.back()的一个拷贝 v2 = 0; // 未改变 c 中的值 }
-
如果希望确保下标是合法的,可以使用at成员函数,如果越界,会抛出异常out_of_range
vector<string> svec; // 空 vector cout<<svec[0]<<endl; // 运行时错误,svec中没有元素 cout<<svrc.at(0); // 抛出一个 out_of_range 异常
-
vector和string不支持push_front、pop_front; forward_listr不支持pop_back
-
erase产出容器中指定位置的元素
list<int> lst = {0,1,2,3,4,5,6,7,8,9}; auto it = lst.begin(); // it指向容器首元素的地址 while (it != lst.end()) if (*it % 2) // (*it) 代表it指向的地址的值 it = lst.erase(it); // 删除此元素, it指向改被删除元素的后一个元素 else ++it; lst.clear(); // 删除容器中所有元素 lst.erase(lst.begin(),lst.end());
-
forward_list中插入或删除元素的操作
lst.before_begin(); lst.cbefore_begin(); // 返回指向链表首元素的之前不存在的元素的迭代器,此迭代器不能解引用 lst.insert_after(p,n,t); // 在之后的位置插入元素,t是一个对象,n是数量 lst.insert_after(p,b,e); // b和e是表示范围的一对迭代器 lst.insert_after(p,li); // li是一个花括号列表 emplace_after(p,args); // 使用args在p指定的位置之后创建一个元素 lst.erase_after(p); // 删除p指向的位置之后的元素 lst.rease_after(b,e); // 删除b指向的,直到e之前的元素
forward_list<int> flst = {1,2,3,4,5,6}; auto prve = flst.before_begin(); // 表示flst的首前元素 auto curr = flst.begin(); // 表示flst的第一个元素 while (curr != flst.end()){ if (*curr % 2) // 当前元素未奇数,则删除;若要删除当前元素,需要先指向其前驱,之后再 erase_after(prve) curr = flst.erase_after(prve); // 返回一个指向被删除的元素之后元素的迭代器 else{ prve = curr; ++curr; } }
- shrink_to_fit 只适用于 vector、string和deque
- capacity():不重新分配内存的情况下 ,容器可以保存多少元素
- reverse(n):分配至少能容纳n个元素的空间
- string:
s.replace(11,3,"3th") 从位置11开始,删除三个元素,并插入3th