9.3.4 特殊的forward_list操作
forward_list并未定义insert、emplace、erase,而是定义了insert_after、emplace_after、erase_after。
------------------------------ | 相关操作 |
---|---|
lst.before_begin() | |
lst.before_cbegin() | 返回指向链表首元素之前不存在的元素的迭代器,此迭代不能解引用,cbegin返回const_iterator类型 |
lst.insert_after(p,t) | |
lst.insert_after(p,n,t) | |
lst.insert_after(p,b,e) | |
lst.insert_after(p,il) | 在迭代器p之后的位置插入元素。t是一个对象,n是数量,b和e是表示范围的一对迭代器,il是一个花括号列表。返回一个指向最后一个插入元素的迭代器。如果范围为空,则返回p,若p为尾后迭代器,则函数行为未定义。 |
emplace_after(p,args) | 使用args在p指定的位置之后创建一个元素。返回一个指向这个新元素的迭代器,若p为尾后迭代器,则函数行为未定义 |
lst.erase_after(p) | |
lst.erase_after(b,e) | 删除p指向位置后的元素,或删除从b之后直到e之间的元素。返回一个指向被删除的元素之后的迭代器。若p指向尾元素或尾后,则函数行为未定义 |
forward_list<int> flst = {1,2,3,4,5,6,7,8,9};
auto prev = flst.before_begin();
auto curr = flst.begin()
while(curr != flst.end())
{
if(*curr % 2)
{
curr = flst.erase_after(prev);
}
else
{
prev = curr;
++curr;
}
}
9.3.5 改变容器的大小
------- | 顺序表大小操作 |
---|---|
c.resize(n) | 调成c的大小为n个元素。若n<c.size(),则多出的元素被丢弃。若必须添加新元素,对元素进行值初始化 |
c.resize(n,t) | 调成c的大小为n个元素,任何新添加的元素都初始化为值t |
resize不适用于array。
9.3.6 容器操作可能使迭代器失效
添加元素:
- 如果容器是vector或string且储存空间被重新分配,则指向容器的迭代器、指针和引用都会失效。如果储存空间未被重新分配,则指向容器的迭代器、指针和引用仍然有效,但指向插入位置之后元素的迭代器、指针和引用将会失效。
- 对于deque,插入到除首位元素之外的任何位置都会导致迭代器、指针和引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。
- 对于list和forwar_list,指向容器的(包括尾后迭代器和首前迭代器)、指针、引用仍有效。
删除元素:
- 对于list和forward_list,指向容器的其他位置的迭代器(包括尾后迭代器和首前迭代器)、指针、引用仍有效。
- 对于deque,如果在首尾元素之外的任何位置删除元素,那么指向被删除元素之外其他元素的迭代器、指针和引用也会失效。如果是删除尾元素,则尾后迭代器也会失效,但其他迭代器、指针和引用不受影响;如果是删除首元素,这些也不会受影响。
- 对于vector和string,指向被删除元素之前元素的迭代器、引用和指针仍有效。当我们删除元素时,尾后迭代器总会失效。
- 编写改变容器的循环程序
vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin();
while(iter! = vi.end())
{
if(*iter % 2)
{
iter = vi.insert(iter, *iter);
iter += 2;
}
else
{
iter = vi.erase(iter);
}
}
- 不要保存end返回的迭代器
auto begin = v.begin();
while(begin() != v.end())
{
++begin;
begin = v.insert(begin(), 42);
++begin;
}