【问题标题】:Why STL containers can insert using const iterator为什么 STL 容器可以使用 const 迭代器插入
【发布时间】: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


    【解决方案1】:

    当一个元素被插入到列表中时,其他元素不会被修改。迭代器仅用于确定插入位置,不用于修改(= 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
    }
    

    【讨论】:

    • 我喜欢这个例子。起初我犹豫了,但实际上这是一个类比。乍一看,Alf 的例子几乎是一样的,即使表述得不太好。
    【解决方案2】:

    它们被称为const_iterators,因为它们不允许您更改基础价值,而不是容器本身。您仍然需要有一个非常量列表来插入元素,因为insert 是std::list 的非常量成员,但接口是以最少限制的方式制作的。

    假设您有一个函数可以让您找到并iterator 到某个元素。它不需要更改任何内容,因此您将其设计为返回const_iterator。然后你想在这个迭代器上插入list,但你不能这样做,如果list的接口受到更多限制的话。

    【讨论】:

      【解决方案3】:

      “我认为 const_iterator 不允许修改容器。”

      你应该注意

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

      其实是std::list的一个非常量成员函数。
      您仍然需要一个可变的 std::list 实例来应用它,容器不会通过迭代器进行修改。 position 参数,只是指定插入新值的位置。

      【讨论】:

        【解决方案4】:

        除了 Spo1ler 的回答,请注意 C++11 更改了一堆库函数来做到这一点:

        [C++11: C.2.12]: 第 23 条:容器库

        23.2.3、23.2.4

        更改: 签名更改:从 iterator 到 const_iterator 参数
        理由: 规格过高。
        效果:以下成员函数的签名从采用iterator 更改为采用const_iterator:

        • insert(iter, val) for vector, deque, list, set, multiset, map, multimap
        • insert(pos, beg, end) for vector, deque, list, forward_list
        • erase(iter) for set, multiset, map, multimap
        • erase(begin, end) for set, multiset, map, multimap
        • list::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) 之间进行选择。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-10
          • 2013-01-05
          • 2014-12-05
          • 2012-01-28
          • 2013-04-16
          • 1970-01-01
          相关资源
          最近更新 更多