顺序容器与关联容器的不同之处在于两者组织元素的方式。
除了array之外,所有标准库容器都提供了灵活的内存管理。在运行时可以动态添加或删除元素来改变容器的大小。
使用push_back
除array和forward_list之外,每个顺序容器(包括string类型)都支持push_back。
容器元素是拷贝:当我们用一个对象来初始化容器时,或将一个对象插入到容器时,实际上放入到容器中的是对象值的一个拷贝,而不是对象本身。
使用push_front
此操作将元素插入到容器头部。list、forward_list和deque容器支持push_front操作,vector不支持。
添加元素
vector<string> svec;
svec.insert(svec.begin(), "hello");
svec.insert(svec.end(), 10, "Anna");
//这行代码将10个元素插入到svec的末尾,并将所有元素都初始化为string“Anna”
list<string> slist;
vector<string> v = { "aa","bb","cc","dd" };
//将v的最后两个元素添加到slist的开始位置
slist.insert(slist.begin(), v.end() - 2, v.end());
slist.insert(slist.end(), {"da","db","ac"});
//运行时错误:迭代器表示要拷贝的范围,不能指向与目的位置相同的容器
slist.insert(slist.begin(), slist.begin(), slist.end());
使用insert返回值
在新标准下,接受元素个数或范围的insert版本返回指向第一个新加入元素的迭代器。
通过使用insert的返回值,可以在容器中一个特定位置反复插入元素:
list<string> lst;
auto iter = lst.begin();
while (cin >> word) {
iter = lst.insert(iter, word);
}
使用emplace操作
新标准引入了三个新成员——emplace_front,emplace和emplace_back,这些操作构造而不是拷贝元素,分别对应push_front、insert和push_back。
emplace函数在容器中直接构造元素。传递给emplace函数的参数必须与元素类型的构造函数相匹配。
访问元素
包括array在内的每个顺序容器都有一个front成员函数,而除了forward_list之外的所有顺序容器都有一个back成员函数。这两个操作分别返回首元素和尾元素的引用。
在容器中访问元素的成员函数(即,front、back、下标和at)返回的都是引用,如果容器是一个const对象,则返回值是const的引用。
删除元素
非array容器的删除函数:改变容器大小
list<int> ilist(10, 42); //10个int:每个的值都是42
ilist.resize(15); //将5个值为0的元素添加到ilist的末尾
ilist.resize(25,-1); //将10个值为-1的元素添加到ilist的末尾
ilist.resize(5); //从ilist末尾删除20个元素
如果当前大小大于所要求的大小,容器后部的元素会被删除;如果当前大小小于新大小,会将新元素添加到容器后部。
容器操作使迭代器失效
向容器中添加/删除元素的操作会使指向容器元素的指针、引用或迭代器失效,一个失效的指针、引用或迭代器将不再表示任何元素。
添加元素:
1)如果容器是vector或string,且存储空间被重新分配,则指向容器的迭代器、指针和引用都会失效。如果存储空间未被重新分配,指向插入位置之前的元素的迭代器、指针和引用仍有效,但指向插入位置之后元素的迭代器、指针和引用将会失效
2)对于deque,插入到首位之外的任何位置都会使迭代器、指针和引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。
3)对于list和forward_list,指向容器的迭代器、指针和引用仍然有效。
删除元素:
1)对于list和forward_list,指向容器的迭代器、指针和引用仍然有效。
2)对于deque,如果在首尾之外的任何位置删除元素,那么指向被删除元素外其它元素的迭代器、引用和指针也会失效。如果是删除deque的尾元素,则尾后迭代器也会失效,但其它迭代器、引用和指针不收影响;如果删除首元素,这些也不会受影响。
3)对于vector和string,指向被删元素之前元素的迭代器、引用和指针仍有效。
当我们删除元素时,尾后迭代器总是会失效。