关于VS2010中vector的insert 有一个奇怪的现象 讨论一下,该如何解决
关于VS2010中vector的insert 有一个奇怪的现象 讨论一下
先上代码
运行结果为
-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的重载就一共两个
第一个不是模板,是确定的const _Ty&类型的参数,而如果编译器认为你的front()版本是不带const的版本,肯定会用第二个insert
------解决方案--------------------
编译器的BUG呀, MS 的编译器BUG本来就不少!
G++没有这个问题的!
只是觉得这么写代码多少有点冒险。
------解决方案--------------------
你这是旧版本吧,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
先上代码
#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++没有这个问题的!
只是觉得这么写代码多少有点冒险。
------解决方案--------------------
你这是旧版本吧,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