for range loop
使用for range loop有个潜在的意思,就是你不要在中间再修改这个容器的大小,尤其不要随便操作迭代器
for range loop等价于实现了begin和end的容器在做一个
1
for(it = begin();it != end();it++)
这个时候如果你要改删除迭代器或者扩容,很可能出问题。尤其要注意在代码逻辑中,一些看似异步的回调,可能很快有sync的操作
在sync操作的时候删除了迭代器,就会出问题
比如欣赏一个sigslot的case,讲道理,emit sig的地方不应该主动的删除掉slot,但架不住工程太大了,比较容易出问题
1
2
3
4
5
6
7
8
9
10
void emit(args... a) {
#if defined(SIGSLOT_ENABLE_THREAD_AFFINITY)
check_thread_affinity();
#endif
internal::lock_block<mt_policy> lock(&(this->m_policy));
// auto connected_slot = this->m_connected_slots;
for (const auto& slot : this->m_connected_slots) {
slot->emit(a...);
}
}
slot->emit的时候如果把操作了当前的m_connected_slots,结果是ub的
迭代器失效
序列的容器都有可能,vector和deque这种可能引起后续元素重排这种,或者扩容导致整体全部移动了, list还好,后续的迭代器不会失效
set和map这种红黑树的结构,属于关联容器,其实也还好,只会导致当前失效
list删除当前迭代器,当前迭代器就无效了,再对它进行操作就可能出问题
不想动脑子的话,拿到迭代器之后,如果你要删除或者扩容,就不要再用这个迭代器了,因为它可能失效了
综合的来讲,删除的时候都需要考虑下,扩容过的时候序列的要考虑下
另外如果一个容器会扩容,尽量不要拿容器back的指针,因为扩容之后会导致之前拿的back的指针失效
This post is licensed under CC BY 4.0 by the author.