我听说现代C++的一个建议是在容器中进行添加时使用
根据标准草案N3797 23.3.6.5 (1),它指出:
在这段代码中:
当使用GCC编译时,输出结果为:
检查VC++中
在
我的问题是: 当容器需要增长时,如果调用
emplace_back
而不是push_back
(emplace_back
接受容器中存储类型的任何构造函数版本的参数)。根据标准草案N3797 23.3.6.5 (1),它指出:
这说明了当不需要重新分配时会发生什么,但在容器需要增长时问题尚未解决。备注:如果新大小大于旧容量,则会导致重新分配。如果没有发生重新分配,则插入点之前的所有迭代器和引用仍然有效。如果除T的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符以外的操作引发异常,那么没有效果。如果非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;
}
使用VC++ (Visual Studio 2013 Update 4)和GCC 4.9.1 (MinGW)在Windows 8.1中以Debug模式编译。
当使用VC++编译时,输出结果为:
1, 2, 3, 4, dd, 2
当使用GCC编译时,输出结果为:
1, 2, 3, 4, 1, 2
检查VC++中
emplace_back
的实现,不同之处在于代码的前几行会检查容器是否需要增长(如果需要则增长),在容器需要增长的情况下,emplace_back
方法中接收到的对第一个元素(buff[0])的引用将失效,并且当在新创建的容器元素中设置值时该值是无效的。在
push_back
的情况下,因为要追加的元素的创建是在参数绑定中完成的(在容器可能增长之前),所以它能够正常工作。我的问题是: 当容器需要增长时,如果调用
emplace_back
并且参数是对同一容器的引用,则此行为是实现定义、未指定或存在编译器实现问题(假设在VC++中,因为GCC的行为更接近期望)?