Mey*_*sam 6 c++ constructor destructor vector erase
我编写了一个简单的程序来测试“vector.erase”功能。有一个简单的类(MyClass0),它在其构造函数中写入一些相关消息,在其析构函数中写入另一个相关消息。然后有一个向量,其中包含 4 个 MyClass0 类型的对象。当我擦除向量的第二个元素时:
vec0.erase(vec0.begin() + 1);
Run Code Online (Sandbox Code Playgroud)
我想屏幕上应该输出“GoodBye From 2”消息。但显示消息“GoodBye From 4”。似乎调用了向量的第四个元素的析构函数。(尽管事实并非如此,因为当“main”完成时,第四个元素将在最后被破坏)。任何人都可以帮助我,以便我找出原因。屏幕上显示的代码和输出是:
代码:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
class MyClass0
{
public:
MyClass0(int i_i_) : i_(i_i_)
{
cout << "Hello From " << this->i_ << endl;
}
~MyClass0()
{
cout << "GoodBye From " << this->i_ << endl;
}
std::string MyToString()
{
return std::string("This is ") + std::to_string(this->i_);
}
private:
int i_;
};
int main()
{
std::vector<MyClass0> vec0 = { MyClass0(1), MyClass0(2), MyClass0(3), MyClass0(4) };
cout << endl << "Before erasing..." << endl;
vec0.erase(vec0.begin() + 1);
cout << "After erase" << endl << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
屏幕上的输出:
Hello From 1
Hello From 2
Hello From 3
Hello From 4
GoodBye From 4
GoodBye From 3
GoodBye From 2
GoodBye From 1
Before erasing...
GoodBye From 4
After erase
GoodBye From 1
GoodBye From 3
GoodBye From 4
Run Code Online (Sandbox Code Playgroud)
她是你的代码修改了一下
class MyClass0
{
public:
MyClass0(int i_i_) : i_(i_i_)
{
cout << "Hello From " << this->i_ << endl;
}
~MyClass0()
{
cout << "GoodBye From " << this->i_ << endl;
}
std::string MyToString()
{
return std::string("This is ") + std::to_string(this->i_);
}
MyClass0(const MyClass0& other) : i_{other.i_}
{
std::cout << "Copy construct " << i_ << '\n';
}
MyClass0& operator=(const MyClass0& other)
{
std::cout << "Asign " << other.i_ << " onto " << i_ << '\n';
i_ = other.i_;
return *this;
}
private:
int i_;
};
Run Code Online (Sandbox Code Playgroud)
揭示了实际发生的情况: https://godbolt.org/z/hW177M7o6
当向量从中间删除项目时,它会通过operator=将项目向左移动来分配项目,然后删除最后一个项目。
矢量中间不允许有任何洞。这意味着当您删除第二个元素时,您实际上并没有删除它。发生的情况是所有元素都向前移动以填充孔,之后向量中的最后一个元素可以被删除,因为它已经向前移动了一次
//start with
1 2 3 4
// erase 2, so move 3 into 2 and 4 into 3
1 3 4 *
// * is old 4 and we don't need that so remove it from the collection
1 3 4
// removing * calls the destructor for that element
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
248 次 |
| 最近记录: |