矢量擦除调用的错误析构函数

Wrong destructor called by vector erase

本文关键字:错误 析构函数 调用 擦除      更新时间:2023-10-16

我有一个包含一些对象的向量。 我注意到,当我使用 erase 方法从矢量中删除一个元素时,我得到了对错误元素的析构函数调用(总是对最后一个元素(。 下面是一个产生错误输出的最小示例。

// Example program
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Test {
public:
Test(string value) {
_value = value;
cout << "Constructor:" << _value << endl;
}
Test(const Test &t) {
_value = t._value;
cout << "Copied:" << _value << endl;
}
~Test() {
cout << "Destructor:" << _value << endl;
}
string print() {
return _value;
}
string _value;
};
int main()
{
vector<Test> vec;
vec.reserve(3);
cout << "Creation" << endl << endl;
vec.push_back(Test("1"));
vec.push_back(Test("2"));
vec.push_back(Test("3"));
cout << endl << "Deleting" << endl << endl;
vec.erase(vec.begin());     // Here is called the element with value "3"
vec.erase(vec.begin());     // Here is called the element with value "3"
cout << endl << "Log" << endl << endl;
// But the final log print "3"
for (unsigned i = 0; i < vec.size(); i++) {
cout << vec[i].print()<<endl;
}
return 0;
}

输出为:

Creation
Constructor:1
Copied:1
Destructor:1
Constructor:2
Copied:2
Destructor:2
Constructor:3
Copied:3
Destructor:3
Deleting
Destructor:3         <-- WRONG, NEED TO BE 1
Destructor:3         <-- WRONG, NEED TO BE 2
Log
3
Destructor:3

我会在不更改容器向量的情况下解决这个问题。

vec.erase(vec.begin());

不会破坏第一个元素。它通过使用移动或复制赋值运算符将所有后续操作移动到一个位置来覆盖它。最后一个元素被移出后剩下的东西就会被破坏,这就是你正在观察的。