假设我有一个包含 5 个元素的 std::vector
V
,
V.erase(V.begin() + 2)
删除第三个元素。
STL vector
实现会将第 4 和第 5 个元素向上移动,然后破坏第 5 个元素。
即删除 vector
中的元素 i 并不能保证调用 ith</em> 析构函数。
对于 std::list
,情况并非如此。删除 ith</em> 元素会调用 ith</em> 元素的析构函数。
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 个位置包含原始内存(不是完全构造的对象 T
)。因此实现需要调用移动构造函数从第 4 个位置移动到第 3 个位置。
它不能销毁第 4 个元素(因为它不能再调用析构函数),然后要从第 5 个元素移动到第 4 个元素,它必须调用移动赋值运算符。
此时,实现仍需要将 vector
大小减 1 并销毁第 5 个元素,但正如我们所见,不允许进行其他 destrucor 调用。 (另请注意,移动赋值运算符不会按照标准要求被调用两次。)QED。
关于c++ - std::vector::erase(iterator position) 不一定调用相应元素的析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17492092/