cpp 容器避坑指南

使用 cpp 中常用容器时,的注意事项。

不要保存 end 返回的迭代器

当我们添加或删除 vectorstring 的元素后,或在 deque 中首元素之外任何位置添加或删除元素后,原来 end 返回的迭代器总是会失效。因此,添加或删除元素的循环程序必须反复调用 end,而不能在循环之前保存 end 返回的迭代器,一直当做容器末尾使用。

std::map 遍历删除元素

对容器进行增、删元素操作,可能会使迭代器失效。关于这一点,复习 《C++ Primer》 P315

正确的写法:(只需要记住正确的写法,其他的即便不是错的也是不规范的)

C++11 标准下,使用 erase() 返回值更新迭代器:返回值 Iterator following the last removed element.

1
2
3
4
5
6
7
// erase all odd numbers from c
for(auto it = c.begin(); it != c.end(); ) {
if(it->first % 2 != 0)
it = c.erase(it);
else
++it;
}

C++11 之前,erase() 成员没有返回值。怎么遍历删除自行 Google 吧

C++11 之前

顺序容器的 erase() 操作返回指向删除的(最后一个)元素之后位置的迭代器。

map.erase() 有 3 个重载:

1
2
3
??? erase ( iterator position );
size_type erase ( const key_type& x );
void erase ( iterator first, iterator last );

在 C++11 之前返回 iteratorerase() 是不符合 STL 标准的

1
2
3
void erase( iterator pos );                (until C++11)
iterator erase( const_iterator pos ); (since C++11)
iterator erase( iterator pos ); (since C++17)

vector 地址

vector 地址、vector 首元素地址以及 vector::data() 的返回值

后两者相等,但和容器地址是两码事。

1
2
3
vector<int> ha = {1, 2, 3};
assert(&ha[0] == ha.data()); // 相等
assert((void*)&ha != ha.data()); // 不相等

参考 :https://stackoverflow.com/a/14825318/6728820

迭代器

迭代器能递加递减,能加一减一吗?

随机访问迭代器 (RandomAccessIterator)是可以的。顺序容器 std::vector 是随机访问迭代器。
http://zh.cppreference.com/w/cpp/concept/RandomAccessIterator

双向迭代器 (BidirectionalIterator)是不可以的。关联容器 std::set std::map 、顺序容器std::list是双向迭代器。
http://zh.cppreference.com/w/cpp/concept/BidirectionalIterator

更多信息请查看:迭代器

http://zh.cppreference.com/w/cpp/iterator/advance

http://zh.cppreference.com/w/cpp/iterator/next

两者的区别:https://stackoverflow.com/questions/15017065/whats-the-difference-between-stdadvance-and-stdnext