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 容器操作可能使迭代器失效

添加元素:

  1. 如果容器是vector或string且储存空间被重新分配,则指向容器的迭代器、指针和引用都会失效。如果储存空间未被重新分配,则指向容器的迭代器、指针和引用仍然有效,但指向插入位置之后元素的迭代器、指针和引用将会失效。
  2. 对于deque,插入到除首位元素之外的任何位置都会导致迭代器、指针和引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。
  3. 对于list和forwar_list,指向容器的(包括尾后迭代器和首前迭代器)、指针、引用仍有效。

删除元素:

  1. 对于list和forward_list,指向容器的其他位置的迭代器(包括尾后迭代器和首前迭代器)、指针、引用仍有效。
  2. 对于deque,如果在首尾元素之外的任何位置删除元素,那么指向被删除元素之外其他元素的迭代器、指针和引用也会失效。如果是删除尾元素,则尾后迭代器也会失效,但其他迭代器、指针和引用不受影响;如果是删除首元素,这些也不会受影响。
  3. 对于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;
}