代码之家  ›  专栏  ›  技术社区  ›  Adrian McCarthy

back_insert_iterator在容器的使用寿命内有效吗?

  •  4
  • Adrian McCarthy  · 技术社区  · 11 月前

    我想我知道这个问题的答案,但我希望能检查一下。

    迭代器无效是否适用于std::back_insert_iterators?

    #include <cassert>
    #include <iterator>
    #include <vector>
    
    int main() {
        auto v = std::vector<int>{ 0, 1, 2 };
        auto iter = std::back_inserter(v);
        *iter++ = 3;
        v.clear();    // invalidates iterators, but
        *iter++ = 4;  //  back_insert_iterator is special?
        assert(v.size() == 1 && v[0] == 4);
        return 0;
    }
    

    这段代码对我有效,因为我的供应商提供的std::back_insert_iterator实现没有迭代器(或指针或引用)。它只是简单地调用容器的push_back方法。

    但是标准 要求 执行?另一个供应商的back_insert_iterator是否可以保存并维护一个one-the-end迭代器,用于调用容器的insert方法?这似乎符合要求。当然,这种区别在于它很容易失效。


    我知道cppreference.com并不权威,但它比标准网站更容易访问。

    [矢量的清除方法][i]验证任何。。。引用所包含元素的迭代器。 任何过期迭代器也将失效。 [ cppreference.com , 增加了强调 ]

    std::back_insert_iterator可能是过端迭代器的海报子代。

    1 回复  |  直到 11 月前
        1
  •  1
  •   NathanOliver    11 月前

    [back.insert.iterator]

    namespace std {
      template<class Container>
      class back_insert_iterator {
      protected:
        Container* container;
    
      public:
        using iterator_category = output_iterator_tag;
        using value_type        = void;
        using difference_type   = ptrdiff_t;
        using pointer           = void;
        using reference         = void;
        using container_type    = Container;
    
        constexpr explicit back_insert_iterator(Container& x);
        constexpr back_insert_iterator& operator=(const typename Container::value_type& value);
        constexpr back_insert_iterator& operator=(typename Container::value_type&& value);
    
        constexpr back_insert_iterator& operator*();
        constexpr back_insert_iterator& operator++();
        constexpr back_insert_iterator  operator++(int);
      };
    }
    

    constexpr explicit back_insert_iterator(Container& x);

    1. 影响 :初始化 container 具有 addressof(x) .

    constexpr back_insert_iterator& operator=(const typename Container::value_type& value);

    2. 影响 :好像通过: container->push_back(value);

    3. 退换商品 : *this .

    constexpr back_insert_iterator& operator=(typename Container::value_type&& value);

    4. 影响 :好像通过: container->push_back(std​::​move(value));

    5. 退换商品 : .

    [...]

    正如我们所看到的,迭代器获取一个指向容器的指针,然后 push_back 直接在容器上调用,因此没有UB的机会。