Mar*_*som 11 c++ vector visual-studio-2010
我正在尝试插入现有vector元素的副本以使其加倍.以下代码在以前的版本中有效,但在Visual Studio 2010中失败.
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> test;
test.push_back(1);
test.push_back(2);
test.insert(test.begin(), test[0]);
cout << test[0] << " " << test[1] << " " << test[2] << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
-17891602 1 2预期产出1 1 2.
我已经弄清楚它为什么会发生 - 向量被重新分配,并且引用在被复制到插入点之前变为无效.较旧的Visual Studio显然以不同的顺序执行操作,从而证明未定义行为的一个可能结果是正确工作并且证明它永远不是您应该依赖的东西.
我想出了两种不同的方法来解决这个问题.一种方法是reserve确保不进行重新分配:
test.reserve(test.size() + 1);
test.insert(test.begin(), test[0]);
Run Code Online (Sandbox Code Playgroud)
另一种是从引用中复制,以便不依赖于引用的剩余有效:
template<typename T>
T make_copy(const T & original)
{
return original;
}
test.insert(test.begin(), make_copy(test[0]));
Run Code Online (Sandbox Code Playgroud)
虽然两者都有效,但两者都不是一种天生的解决方案.有什么我想念的吗?
我相信这是定义的行为。在\xc2\xa723.2.32011 C++ 标准中,表 100 列出了序列容器要求,并且有一个针对这种情况的条目。它给出了示例表达式
a.insert(p,t)\nRun Code Online (Sandbox Code Playgroud)\n\n其中a是一个值,X它是包含类型元素的序列容器类型T,p是 的 const 迭代器a,并且t是类型 的左值或常量右值X::value_type,即T。
该表达式的断言是:
\n\n\n\n\n要求:
\nT应CopyInsertable进入X. 为vector且deque,T应也CopyAssignable。\n
效果:t插入before的副本p。
我能找到的唯一相关向量特定引用是在\xc2\xa723.3.6.5第 1 段中:
\n\n\n备注:如果新大小大于旧容量,则导致重新分配。如果没有发生重新分配,则插入点之前的所有迭代器和引用仍然有效。
\n
insert尽管这确实提到了重新分配的向量,但它并没有对先前对顺序容器的要求造成例外。
至于解决这个问题,我同意 @EdChum 的建议,即只制作元素的副本并插入该副本。
\n