假设我有一个5个元素的std :: vector V,
V.erase(V.begin()2)删除第3个元素.
STL向量实现将向上移动第4和第5个元素,然后破坏第5个元素.
即向量中的擦除元素i不保证调用第i个析构函数.
对于std :: list,情况并非如此.擦除ith元素调用ith元素的析构函数.
STL对这种行为有什么看法?
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个位置包含原始内存(不是完全构造的对象T).因此,实现需要调用移动构造函数从第4个位置移动到第3个位置.
它不能破坏第4个元素(因为它不能再调用析构函数),然后从第5个元素移动到第4个元素,它必须调用移动赋值运算符.
此时,实现仍需要将向量大小减小1并销毁第5个元素,但正如我们所见,不允许其他destrucor调用. (另请注意,移动分配运算符不会按标准要求调用两次.)QED.