关于 C++ vector 的两个小 tips

原本这篇文章标题我想起成《关于 vector 的两个小坑》,后来想一想,其实也不算是坑,仍是本身对原理性的东西理解的没作那么透彻。工做中遇到的不少问题,后来归根到底都是基础不牢靠。安全

vector 扩容

这个问题很经典了,但仍是不当心踩到。有一个需求是要对目标元素进行复制,而目标元素集合是保存在 vector 里面,因而简单思考下就有以下代码(大体含义):函数

void Duplidate(vector<Element>* element_list, Element* element) {
  element_list.push_back(*element);
}

void Process() {
  for (auto& package : package_list) {
    if (IsNeedDuplicate()) {
      Duplicate(element_list, package->element);
    }
  }
}

看起来好像没什么问题,就是当前的 package 对象是否知足复制的要求,须要的话,就对 package 的成员 origin_element 进行复制。跑 UT 也正常,而后在测试的时候就 coredump 了。看 core 文件就是挂在了复制的时候。这里我一开始就没明白,一个简单的复制为何会有 coredump。学习

检查了好久 element 复制的场景,甚至想要专门写一个拷贝构造函数。最后才恍然大悟,origin_element 指针指向的就是 element_list 里面的元素,element_list 是总体流程的数据源,packge 对象是封装的中间处理对象。以前的开发人员为了方便,直接在 package 对象上保存了原始的 element 指针,而这个指针指向的是一个 vector 里的元素。而我新加的逻辑会往原始的 vector 里面再添加元素,那么就有可能致使 vector 扩容,而 vector 扩容会致使总体的复制,从而致使原来指向这些元素的指针都失效了,靠后的 package 对象再去访问 origin_element 就产生了 coredump。测试

固然,从设计上来讲,就不该该保存指向 vector 元素的指针,可是这里有太多旧代码牵涉,这里就不作讨论。设计

vector::erase()

原由是我在代码里面新增了以下代码(大体):指针

void EraseElement(const vector<Element>::iterator& element_iter,
                vector<Element>& element_list) {
  while (element_iter != element_list.end()) {
    element_list.erase(element_iter);
  }
}

而后 cr 的同窗提出了一个疑问是 element_iterconst 不可变的,可是在函数里有擦除了对应的元素,这里会不会有问题?虽然 UT 都已经跑过了,可是这种写法的确比较奇怪,因而就借机学习了一下 vector::erase() 的实现原理跟用法。code

erase(iterator) 的实现原理其实不会改变 iterator,而是把后面的元素一个个往前移动,至关因而 iterator 指向的元素自己发生了变化,因此能够用 const 来修饰这个 iterator。可是这里用 cosnt & 实际上是没有错可是无用的修饰,除了容易让人误判以外,其实没有什么实际用途。我以前是为了修正 cpplint 才把reference 改为 const reference。对象

另外 erase 自己的确比较危险,主要仍是 erase 的时候 iterator 自己没发生变化,可是指向的元素变了,,在不少时候 iterator 会天然地指向下一个元素,可是因为这是未定义的行为,这里面可能会有不可预期的地方,因此最终改为显示的获取返回从新赋值(erase() 会返回下一个迭代器,但这一点经常被忽略),这样就能保证安全性了。更安全更推荐的作法应该是使用 remove_if() 这里就不展开讲了。element

void EraseElement(vector<Element>& element_list,
                vector<Element>::iterator element_iter ) {
  while (element_iter != element_list.end()) {
    element_iter = element_list.erase(element_iter);
  }
}
相关文章
相关标签/搜索