【发布时间】:2015-03-01 14:44:18
【问题描述】:
为什么 STL 容器可以使用const_iterator 插入?比如有
iterator std::list::insert (const_iterator position, const value_type& val);
我认为const_iterator's 不允许修改容器。
【问题讨论】:
标签: c++ stl iterator constants
为什么 STL 容器可以使用const_iterator 插入?比如有
iterator std::list::insert (const_iterator position, const value_type& val);
我认为const_iterator's 不允许修改容器。
【问题讨论】:
标签: c++ stl iterator constants
当一个元素被插入到列表中时,其他元素不会被修改。迭代器仅用于确定插入位置,不用于修改(= call non-const member function on)任何现有元素。
即使erase 也可以使用const_iterator。同样,这是因为删除元素也不会修改它。这听起来可能很奇怪,但如果考虑到这一点,那就微不足道了:
void f()
{
std::string const s = "foo";
// the function ends and s is destroyed even though it was constant
}
【讨论】:
它们被称为const_iterators,因为它们不允许您更改基础价值,而不是容器本身。您仍然需要有一个非常量列表来插入元素,因为insert 是std::list 的非常量成员,但接口是以最少限制的方式制作的。
假设您有一个函数可以让您找到并iterator 到某个元素。它不需要更改任何内容,因此您将其设计为返回const_iterator。然后你想在这个迭代器上插入list,但你不能这样做,如果list的接口受到更多限制的话。
【讨论】:
“我认为 const_iterator 不允许修改容器。”
你应该注意
iterator std::list::insert (const_iterator position, const value_type& val);
// ^^^^^^
其实是std::list的一个非常量成员函数。
您仍然需要一个可变的 std::list 实例来应用它,容器不会通过迭代器进行修改。 position 参数,只是指定插入新值的位置。
【讨论】:
除了 Spo1ler 的回答,请注意 C++11 更改了一堆库函数来做到这一点:
[C++11: C.2.12]:第 23 条:容器库23.2.3、23.2.4
更改: 签名更改:从
iterator到const_iterator参数
理由: 规格过高。
效果:以下成员函数的签名从采用iterator更改为采用const_iterator:
insert(iter, val)forvector,deque,list,set,multiset,map,multimapinsert(pos, beg, end)forvector,deque,list,forward_listerase(iter)forset,multiset,map,multimaperase(begin, end)forset,multiset,map,multimaplist::splice的所有形式- 所有形式的
list::merge使用这些函数的有效 C++ 2003 代码可能无法使用此国际标准进行编译。
例如:
他们这样做是因为他们最初假设了您的做法,但后来意识到这毫无意义,并无缘无故地让人头疼。它被“过度指定”了。
const_iterator 有助于保证 element 在迭代范围时的不变性,但如果它还意味着您不能使用它来描述容器中的位置,那将是不必要的限制执行突变。如果您需要这两种行为,您始终可以让容器本身在该范围内为 const。
不过需要注意的是this change isn't universally liked, because:
map::erase(和几个相关方法)在 C++03 中采用了迭代器,但在 C++0x 中采用了const_iterator。这会破坏地图的key_type具有接受迭代器的构造函数(例如模板构造函数)的代码,因为编译器无法在erase(const key_type&)和erase(const_iterator)之间进行选择。
【讨论】: