是否允许将 std::vector 的元素插入到同一向量中?

Is inserting an element of a std::vector into the same vector allowed?

考虑 std::vector<T> 的以下 insertemplace 成员函数:

template <class... Args> iterator emplace(const_iterator position, Args&&... args);
iterator insert(const_iterator position, const T& x);
iterator insert(const_iterator position, T&& x);
iterator insert(const_iterator position, size_type n, const T& x);

如果其中一个以对向量本身的元素作为参数的引用被调用怎么办?通常,它们中的每一个都会使对从 position 开始的所有元素的引用无效,这可能包括参数,或者如果发生重新分配,对 all 元素的引用,这肯定包括它,但这是否意味着这样的调用无效或插入(似乎)先发生?

查看一些常见的实现会得出奇怪的结果:

我是否错过了标准定义此行为的地方?为什么我查看的三个 C++ 库彼此不一致?为什么 libstdc++ 评论说它只是 insert(const_iterator, const T&) 的问题?如果标准不要求它起作用,为什么图书馆还要费心让它起作用呢? (当然,这会花费一些副本 and/or 移动,否则可以避免。)最后,如果我要实现一个应该类似于 std::vector 的容器,我应该让它工作吗?

首先回答第二个问题:标准明确表示允许标准库假设当通过右值引用传递某些东西时,右值引用是 only 引用那个对象。这意味着它不能合法地成为矢量的元素。 C++11 17.6.4.9/1相关部分:

  • If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument. ... [ Note: If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g. by calling the function with the argument move(x)), the program is effectively asking that function to treat that lvalue as a temporary. The implementation is free to optimize away aliasing checks which might be needed if the argument was an lvalue. —end note ]

这让我们只需要处理 const T & 案例。尽管 libstdc++ 和 libc++ 在这种情况下有所不同,但它们的最终结果是相同的——它们将从传入的对象中正确复制。标准只规定了行为,没有规定实现。只要他们达到正确的行为,他们就没事。