我偶尔在 VS2010 中发现一个奇怪的问题,下一个代码:
void Test1()
{
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.insert(vec.end(), vec[0]);
// GCC: vec == [10, 20, 10];
// VS2005: vec == [10, 20, 10];
// VS2010: vec == [10, 20, -17891602];
}
似乎向量在读取新值之前会重新分配内存并删除旧内存,这会导致复制损坏的值。VS2010 中存在此问题。检查 VS2005 和 GCC - 好的。
将来自 operator[] 或 front()/back() 方法的引用传递给 insert() 是否有效?
UPD:根据以下评论进行了一些调查后,我得出的结论是,由于性能原因,使用 reserve() 并不是一个好主意。它会导致不必要的大量重新分配。
void Test2()
{
std::vector<int> vec, vec2;
const int count = 10000;
int prevCap = 0, reallocCount = 0;
int prevCap2 = 0, reallocCount2 = 0;
for (int i = 0; i < count; ++i)
{
if (vec.size() >= vec.capacity())
{
vec.reserve(vec.size()+1);
}
vec.insert(vec.end(), i);
vec2.insert(vec2.end(), i);
const int cap = vec.capacity();
const int cap2 = vec2.capacity();
if (prevCap != cap) ++reallocCount;
prevCap = cap;
if (prevCap2 != cap2) ++reallocCount2;
prevCap2 = cap2;
}
cout << reallocCount << " " << reallocCount2 << endl;
// reallocCount == 10000, reallocCount2 == 15 GCC
}
所以现在我只有两个选择:
1)使用临时变量
const int tempValue = vec[0];
vec.insert(vec.end(), tempValue);
但是我不确定编译器是否可以通过一些优化来删除 tempValue。
2) 使用 push_back(0) 和更多 pop_back() 调用
vec.push_back(0);
vec.pop_back();
vec.insert(vec.end(), vec[0]);
这种方法似乎更好,它在 VS2005/2010 和 GCC 中给出了预期的结果和性能。
我错过了什么?有更好的解决方案吗?