EMCPP条款13:优先选用const_iterator,而非iterator
const_iterator
是 STL 中相当千指涉到 const
的指针的等价物。它们指涉到不可被修改的值。只要有可能就应该使用 const
的标准实践表明,任何时候只要你需要一个迭代器而其指涉到的内容没有修改必要,你就应该使用 const_iterator
。
比如,假设你想在 std::vector<int>
中搜索第一次出现的 1983
(这一年,”C++”取代了”带类的C”成为了该种程序设计语言的名字),然后在此位置插入值 1998
(这一年,首个ISO C++ 标准被接受)。如果 vector
中并无 1983
, 那么插入位置将是其末尾处。在 C++98 中使用 itera tor
来实现,很容易:
1 | std::vector<int> values; |
但在这里使用 iterator
并非正确选择,因为代码中并无任何地方修改了 iterator
指涉到的内容。修订这段代码以使用 const_iterator
本应是举手之劳 , 可是在 C++98 中,要费很大工夫。下面是一种在概念上貌似站得住脚的途径,但其实并不正确:
1 | typedef std::vector<int>::iterator IterT; |
C++11 中,这些现象彻底改观了。获取和使用 const_iterator
都变得容易了。
1 | std::vector<int> values; // as before |
只有一种情景下,C++11 对于 const_iterator
的支持显得不够充分,那就是你想撰写最通用化的库代码的时候。这些代码会考虑到,某些容器,或类似容器的数据结构会以非成员函数的方式提供 begin
和 end
(还有 cbegin
、cend
和 rbegin
等),而不是以成员由数方式。所以,最通用化的代码会使用非成员函数,而不会假定其成员函数版本的存在性。
举例来说,刚才我们写的这段代码可以写成下面 findAndInsert
模板的通用形式:
1 | template<typename C, typename V> |
以上代码在 C++14 中可以完全正常运行,但可惜的是,在 C++11 中却不行。由于在标准化过程中的短视,C++11 仅添加了非成员函数版本的 begin
和 end
, 而没有添加 cbegin
、cend
、rbegin
、rend
、crbegin
和 crend
。C++14 纠正了这种短视。
要点速记
- 优先选用
const_iterator
, 而非iterator
。 - 在最通用的代码中,优先选用非成员函数版本的
begin
、end
和rbegin
等,而非其成员函数版本。