关于VS2010中vector的insert 有一个奇怪的现象 讨论一下,该如何解决

关于VS2010中vector的insert 有一个奇怪的现象 讨论一下
先上代码 


#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
vector<int> nArr;
nArr.push_back(1);

vector<int> nArr1 = nArr;
nArr1.insert(nArr1.end(), nArr1.front());

vector<int> nArr2 = nArr;
const int& n1 = nArr2.front();
nArr2.insert(nArr2.end(), n1);

vector<int> nArr3 = nArr;
nArr3.push_back(nArr3.front());

vector<int> nArr4 = nArr;
nArr4.push_back((int&&)nArr4.front());

cout << nArr1[1] << "\n" << nArr2[1] << "\n" << nArr3[1] << "\n" << nArr4[1] << "\n";

return 0;
}

运行结果为 
-572662307
1
1
1

也就是说  nArr1.insert(nArr1.end(), nArr1.front());  会出错 
跟踪了一下代码,有一些不理解的地方 
1.  出错的是 template<class _Valty> iterator insert(const_iterator _Where, _Valty&& _Val)这个接口
而iterator insert(const_iterator _Where, const _Ty& _Val) 没有问题 
为什么 nArr.front() 或者 nArr[0] 会被当做 int&& 而不是 const int& ?
2.  push_back的时候 默认执行的是 void push_back(const _Ty& _Val)  而不是void push_back(_Ty&& _Val)
当强制转为 int&& 时  也没错  这是什么原因?
3. 在vs2005上试的时候 没有这个问题  而且也不觉得 nArr1.insert(nArr1.end(), nArr1.front());  有什么不妥当的地方  
是否可以说 这是vs2010 STL的一个BUG?


------解决方案--------------------
跟进去看看,有可能是编译器bug
insert导致vec重新分配内存,但是没有检测实参仍然在原内存中, 直接把原内存块释放了。纯属猜测, 没有vc 2010, 不能证实。 
------解决方案--------------------
经过初步调查VS2010的STL实现,我顶mujiok2003,认为这是一个BUG。

VS2010的nsert实现是先释放原始空间,再给新位置赋值的,对传入数组本身元素的情况明显考虑不充分。

第二点,关于编译器为啥选择右置版本的insert很好解释。因为insert的重载就一共两个

iterator insert(const_iterator _Where, const _Ty& _Val);

template<class _Valty>
iterator insert(const_iterator _Where, _Valty&& _Val);


第一个不是模板,是确定的const _Ty&类型的参数,而如果编译器认为你的front()版本是不带const的版本,肯定会用第二个insert
------解决方案--------------------
编译器的BUG呀, MS 的编译器BUG本来就不少!
G++没有这个问题的!

只是觉得这么写代码多少有点冒险。
------解决方案--------------------
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

Quote: 引用:

Quote: 引用:

Quote: 引用:

lz, 你就不能自己跟踪代码吗? 几分钟就清楚的事情。 


已经写的这么详细了  拜托从头看一遍好么?
为什么你们都认为我没看过 effective stl?
为什么你们都认为这样写代码不合理?
我知道出错是怎么执行的 我就想知道  这样的问题是故意的吗?
明明可以在STL的代码里避免 为什么非要挖这样的坑?


淡定。 我认为这代码OK, 应该是stl bug,也许已经fix了。 vc 2013没有这个问题: 
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.30501 for x86

论坛里有些人, 总推荐书目,就不说问题。 

没错不代表正确
已经踩一次坑了就不要在写这种有隐患的代码了。

我不认为这是C++ stl的问题, 应该是某个STL有bug.  insert可能到时iterator,reference失效不假, 那是insert执行之后的事情。 insert内部有义务处理这种情况。 


C++标准是这么说的
Causes reallocation if the new size is greater than the old capacity. If no reallocation happens,
all the iterators and references before the insertion point remain valid
例外情况不规定,那就是说:insert内部处理了这种情况没问题,insert不处理这种情况也没问题。
总之这种有坑的代码,踩上一次就别在踩了。

vector很有很多成员都是value_type const&, 比如assign, resize , push_back, insert等, 这些函数都没有规定要处理这种情况。 至少也要说明这是implemention defined。 要不然,我是不敢用了这些函数, 太危险了,我可以不写v.push_back(v.back()); 这样的代码,但是难免写出v.push_back(i); 而i是一个value_type的实参。 

当然,区间版本的insert是显示规定了的。 
关于VS2010中vector的insert 有一个奇怪的现象 讨论一下,该如何解决

你这是旧版本吧,2011版的标准 针对 insert emplace_back emplace push_back 都是一样的
Causes reallocation if the new size is greater than the old capacity. If no reallocation happens,
all the iterators and references before the insertion point remain valid