vector::insert在VS2010中执行意想不到的结果
vector::insert in VS2010 performs unexpected result
我偶尔在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];
}
似乎vector在读取新值之前重新分配内存并删除旧内存,这导致了损坏值的复制。这个问题在VS2010中存在。在VS2005和GCC中检查- OK
传递给insert()从操作符[]或front()/back()方法中获取的引用是否有效?
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中给出了预期的结果和性能。
我错过什么了吗?有没有更好的解决方案?
insert通过引用接受第二个参数。Op[]也提供了参考。调用insert会使引用无效,因此会有未定义的行为,任何事情都可能发生。
插入的文档说(我强调)
通过在元素at之前插入新元素来扩展vector指定的位置,有效地增加了容器的尺寸插入的元素数。
这将导致自动重新分配已分配的存储空间当且仅当新向量的大小大于当前向量能力。
由于insert
的第二个参数是一个引用,重新分配可能需要重新定位堆单元,这表明只有当您知道重新分配不会发生时,您的代码才是安全的。即当vec.capacity() > vec.size()
正如Agnew和quetzalcoatl所指出的,有几种方法可以修复你的代码
您可以将新值复制到临时值,以确保对它的引用仍然有效
int val = vec[0];
vec.insert(vec.end(), val);
…或者你可以在调用insert
if (vec.capacity == vec.size()) {
vec.reserve(vec.size()+1);
}
vec.insert(vec.end(), val);
- 为什么在递归中使用循环会产生意想不到的结果?
- 字符到int8_t转换会产生意想不到的结果?
- libc++ 对 std::map/set::equal_range 的实现给出了意想不到的结果
- 微小加密算法实现会产生意想不到的结果
- 使用 std::set 的 .begin() 和 .end() 函数会产生意想不到的结果
- 在我的C++链表实现中取消引用节点指针,给出意想不到的结果
- C++正则表达式Visual Studio Community 2015给出<regex>意想不到的结果
- istringstream int8_t产生意想不到的结果
- 划分 OpenCV 垫会产生意想不到的结果
- 提升精神,提升任何意想不到的结果
- regex_match给出意想不到的结果
- 从 PASCAL 到 C++ 的代码转换给出了意想不到的结果
- 意想不到的结果c++
- 在lambda上使用条件运算符调用std::any_of会得到意想不到的结果
- vector::insert在VS2010中执行意想不到的结果
- list resize会产生意想不到的结果
- CUDA: 2D数组索引产生意想不到的结果
- 将字符串转换为整数会产生意想不到的结果
- 在c++中,一些宏语句可能会产生意想不到的结果
- Visual Studio可变宏展开会产生意想不到的结果