c – std :: vector :: erase(迭代器位置)不一定会调用相应元素的析构函数

前端之家收集整理的这篇文章主要介绍了c – std :: vector :: erase(迭代器位置)不一定会调用相应元素的析构函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
假设我有一个5个元素的std :: vector V,

V.erase(V.begin()2)删除第3个元素.

STL向量实现将向上移动第4和第5个元素,然后破坏第5个元素.

即向量中的擦除元素i不保证调用第i个析构函数.
对于std :: list,情况并非如此.擦除ith元素调用ith元素的析构函数.

STL对这种行为有什么看法?

这是从我的系统的stl_vector.h获取代码

392   iterator erase(iterator __position) {
393     if (__position + 1 != end())
394       copy(__position + 1,_M_finish,__position);
395     --_M_finish;
396     destroy(_M_finish);
397     return __position;

解决方法

C 11标准23.3.6.5/4说(重点是我的):

Complexity: The destructor of T is called the number of times equal to the number of the elements erased,but the move assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements.

如果实现在第3个元素上调用了析构函数,则它将不符合.

实际上,假设在第3个元素上调用析构函数.由于只擦除了一个元素,因此无法再次调用析构函数.

在析构函数调用之后,第3个位置包含原始内存(不是完全构造的对象T).因此,实现需要调用移动构造函数从第4个位置移动到第3个位置.

它不能破坏第4个元素(因为它不能再调用析构函数),然后从第5个元素移动到第4个元素,它必须调用移动赋值运算符.

此时,实现仍需要将向量大小减小1并销毁第5个元素,但正如我们所见,不允许其他destrucor调用. (另请注意,移动分配运算符不会按标准要求调用两次.)QED.

猜你在找的C&C++相关文章