为什么STL容器可以使用const迭代器插入

时间:2015-03-01 14:44:19

标签: c++ stl iterator const

为什么STL容器可以使用const_iterator插入?例如,有

iterator std::list::insert (const_iterator position, const value_type& val);

我原以为const_iterator不允许修改容器。

4 个答案:

答案 0 :(得分:2)

它们被称为const_iterator,因为它们不允许您更改基础值,而不是容器本身。你仍然需要一个非const列表来插入元素,因为insertstd::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

     

更改:签名更改:从iteratorconst_iterator参数
  理由:过度规范。
  效果:以下成员函数的签名从将iterator更改为const_iterator更改为

     
      
  • insert(iter, val)代表vectordequelistsetmultisetmapmultimap
  •   {li> insert(pos, beg, end) vectordequelistforward_list   {li> erase(iter) setmultisetmapmultimap   {li> erase(begin, end) setmultisetmapmultimap   
  • 所有形式的list::splice
  •   
  • 所有形式的list::merge
  •   
     

使用这些函数的有效C ++ 2003代码可能无法使用此国际标准进行编译。

例如:

他们之所以这样做,是因为他们最初采用了你的方式,但后来意识到这没有任何意义,并且无缘无故引起了人们的头痛。它被过度指定"。

const_iterator有助于在迭代范围内保证元素不变性,但如果它也意味着您无法使用它来描述某个位置,那么这将是不必要的限制在容器中进行突变。如果您需要这两种行为,您始终可以将容器本身设置为const

但应注意this change isn't universally liked, because

  

map::erase(和几个相关的方法)在C ++ 03中使用了一个迭代器,但是在C ++ 0x中使用const_iterator。这会打破代码,其中map key_type具有接受迭代器的构造函数(例如模板构造函数),因为编译器无法在erase(const key_type&)erase(const_iterator)之间进行选择。