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

2024-05-18

考虑以下insert and emplace的成员函数std::vector<T>:

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元素,其中肯定包含它,但这是否意味着这样的调用无效或者插入(似乎)首先发生?

查看一些常见的实现会产生奇怪的结果:

  • libstdc++ 在移动任何元素之前复制参数,但仅限于const T&的过载insert。它包含这样的评论:

    这三个操作的顺序由 C++0x 规定 情况下,移动可能会改变属于的新元素 到现有的向量。这只是呼叫者的问题 通过 const lvalue ref 获取元素(参见 23.1/13)。

    但 C++11 §23.1 只是容器库的简要总结,即使我们假设它指的是 §23.2.1(在 C++03 中曾经是 §23.1),也只是 §23.2.1/13给出了分配器感知容器的定义,这似乎与此无关。我已经浏览了第 23 章,但没有找到任何相关内容。

  • libc++ 在移动任何元素之前创建一个临时文件emplace, 而在insert它首先移动元素,但将参数引用转换为指针并调整它以确保它指向原始元素 - 但同样,它仅在const T&超载。

  • 在所有情况下,Visual C++ 在移动任何元素之前都会创建一个副本/临时文件。

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


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

  • 如果函数参数绑定到右值引用参数,则实现可以假设 此参数是对此参数的唯一引用。 ... [Note:如果程序将左值转换为 xvalue,同时将该左值传递给库函数(例如,通过使用参数调用该函数move(x)),程序实际上要求该函数将该左值视为临时值。这 实现可以自由地优化别名检查,如果参数是,则可能需要 左值。——尾注 ]

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐