GCC和VC++之间std :: vector :: emplace_back的区别

Net*_*peC 8 c++ gcc stdvector visual-c++ c++11

我听说Modern C++的一个建议是使用emplace_back而不是push_back在容器中追加(emplace_back接受容器中任何类型存储的构造函数的任何版本的参数).

根据标准草案N3797 23.3.6.5(1),说:

备注:如果新大小大于旧容量,则会导致重新分配.如果没有重新分配,插入点之前的所有迭代器和引用仍然有效.如果除了复制构造函数之外抛出异常,移动构造函数,赋值运算符或T的移动赋值运算符,或者通过任何InputIterator操作都没有效果.如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果.

这指定了在不需要重新分配时会发生什么,但在容器需要增长时保持打开问题.

在这段代码中:

#include <iostream>
#include <vector>

int main() {
    std::vector<unsigned char> buff {1, 2, 3, 4};
    buff.emplace_back(buff[0]);
    buff.push_back(buff[1]);
    for (const auto& c : buff) {
        std::cout << std::hex << static_cast<long>(c) << ", ";
    }
    std::cout << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译VC++(Visual Studio的2013更新4)GCC 4.9.1(MinGW的)调试在Windows 8.1.

使用VC++编译时,输出为:

1, 2, 3, 4, dd, 2
Run Code Online (Sandbox Code Playgroud)

使用GCC编译时,输出为:

1, 2, 3, 4, 1, 2
Run Code Online (Sandbox Code Playgroud)

检查emplace_backVC++中的实现差异在于第一行代码,检查容器是否需要增长(如果需要则增长),在容器需要增长的情况下,引用第一个元素(buff [ 0])在emplace_back方法中接收到无效,并且当容器的新创建元素中的值的实际设置发生时,该值无效.

在工作的情况下,push_back因为要在参数绑定中创建要追加的元素(在容器可能增长之前).

我的问题是:这种行为,当容器需要增长时因为调用emplace_back而参数是对同一容器的引用是实现定义,未指定或者在编译器的实现中存在问题(假设在VC++中为海湾合作委员会的行为更接近预期)?

小智 0

当您使用 &operator[] 时,它返回一个引用。然后,您使用 emplace_back 导致重新分配,从而使所有过去的引用无效。这两条规则都有明确的定义。应该发生的正确事情是例外。实际上,如果您在调试器下运行调试版本,我实际上希望 VC++ 版本会抛出异常。

Push_back 有相同的两个规则,这意味着它也会做同样的事情。我几乎可以肯定,交换两行 emplace_back/push_back 将导致相同的行为。