今天同事贴出一段代码,运行的输出是原来所没有注意到的,代码如下:
struct C {
int id;
C(int n) : id(n) {}
~C() { printf( "~C() id=%d\n", id); }
};
void main()
{
std::vector vec;
vec.reserve(5);
for (int i = 1; i <= 5; i++) vec.push_back(C(i));
cout << "\nhero we go..." << endl;
cout << "-------- before del ------------" << endl;
vec.erase( vec.begin() );
cout << "-------- after del ------------" << endl;
}
输出结果如下:
XXX> simpleTest.exe
~C() id=1
~C() id=2
~C() id=3
~C() id=4
~C() id=5
hero we go...
1
2
3
4
5
-------- before del ------------
~C() id=5
-------- after del ------------
~C() id=2
~C() id=3
~C() id=4
~C() id=5
结论:对象5被析构了两次,1没被析构!
讨论:
A(楼主) :
底层确实是这么做的,
先memmove覆盖,然后在最后位置调用析构,
但是这样设计和实现貌似不严谨,需要推敲一下哦。
为什么不先就地析构,然后在memmove呢?效率无差别,更严谨,没这问题
B:
随便猜啊,是不是先析构,再memmove的话,内存需要重新分配呢?
C:
删除第一个节点,内部操作是把第2到第5个元素搬到第一到第四个元素的位置上,调用的是 = 操作,然后再把第5个元素析构掉
A:
楼上正解,但是感觉这么搞不大严谨啊
C:
vector建议只在尾部进行操作,不建议在头部进行操作,要不然是有问题,特别是在析构函数中做一些保存操作的时候
用list就不会有这个问题
D:
用容器存储value(不是pointer),还用析构来实现一些逻辑,本身就不大对。
E:
template
typename vector<_Tp,_Alloc>::iterator
vector<_Tp,_Alloc>::
erase(iterator __position)
{
if (__position + 1 != end())
std::copy(__position + 1, end(), __position);
--this->_M_impl._M_finish;
std::_Destroy(this->_M_impl._M_finish);
return __position;
}
F:
iterator erase(iterator _P)
{copy(_P + 1, end(), _P);
_Destroy(_Last - 1, _Last);
--_Last;
return (_P); }
在erase的时候先拷贝了,_Destroy的却是最后一个元素...
G:
应该要重载类的operator=()这个函数。就不会有什么问题了。
因为vector是用赋值操作进行元素的拷贝或移动的。所以要重载类的operator=()这个函数。导致的结果是效率低下。但不会造成成内存泄漏。
阅读(640) | 评论(0) | 转发(0) |