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