考虑如下代码:
std::vector<int> values;
std::vector<int>::iterator it = std::find(values.begin(), values.end(), 1983);
values.insert(it, 1998);
如果vector
中并没有1983,那么插入位置将是末尾处。但在这里使用iterator
并非正确选择,因为代码中并无任何i地方修改了iterator
指向涉的内容。
typedef std::vector<int>::iterator IterT;
typedef std::vector<int>::const_iterator ConstIterT;
std::vector<int> values;
ConstIterT ci = std::find(static_cast<ConstIterT>(values.begin()), // 强制类型转换
static_cast<ConstIterT>(values.end()), // 强制类型转换
1983);
values.insert(static_cast<IterT>(ci), 1998); // 可能无法通过编译(从const_iterator到iterator并不存在可移植的
// 类型转换)
在std::find
的调用中之所以要加上强制类型转换,是因为values
是C++98
中的非const容器,而并没有什么简单的办法能从一个非const
容器得到对应的const
容器。
而一旦得到了const_iterator
,往往事态变得糟糕,因为在C++98
中插入/删除的位置只能以iterator
指定,而不接受const_iterator
C++11
中这种现象彻底改观了,获取和使用const_iterator
都变得容易了。容器的成员函数cbein
和cend
都返回const_iterator
类型:
std::vector<int> values;
auto it = std::find(values.cbegin(), values.cend(), 1983);
values.insert(it, 1998);
只有一种情景下,C++11
对于const_iterator
的支持显得不够充分,那就是在撰写最通用化的库代码的时候:
template <typename C, typename V>
void findAndInsert(C& container,
const V& targetVal,
const V& insertVal)
{
using std::cbegin;
using std::cend;
auto it = std::find(cbegin(container),
cend(container),
targetVal);
container.insert(it, insertVal);
}
以上代码在C++14
中可以正常运行,在C++11
中仅添加了非成员函数版本的begin
和end
,而没有i添加cbegin, cend, rbegin,crbegin,crend
;