我正在尝试理解在将新值分配给在栈上分配的对象时出现的一些奇怪行为(析构函数会针对相同的数据集被调用两次)。我将从代码片段及其输出开始:
class Foo {
public:
Foo(const string& name) : m_name(name) {
log("constructor");
}
~Foo() {
log("destructor");
}
void hello() {
log("hello");
}
private:
string m_name;
void log(const string& msg) {
cout << "Foo." << this << " [" << m_name << "] " << msg << endl;
}
};
int main() {
{
Foo f {"f1"};
f.hello();
f = Foo {"f2"};
f.hello();
}
cout << "scope end" << endl;
}
输出:
Foo.0x7fff58c66a58 [f1] constructor
Foo.0x7fff58c66a58 [f1] hello
Foo.0x7fff58c66a18 [f2] constructor
Foo.0x7fff58c66a18 [f2] destructor
Foo.0x7fff58c66a58 [f2] hello
Foo.0x7fff58c66a58 [f2] destructor
scope end
我预期会发生以下事情:
- 在堆栈上创建/初始化0x...58
- 在堆栈上创建/初始化0x...18
- Foo析构函数在0x...58上被调用(使用f1数据)
- Foo析构函数在0x...18上被调用(使用f2数据)
实际发生的情况:
- 在堆栈上创建/初始化0x...58
- 在堆栈上创建/初始化0x...18
- 从0x...18(f2)复制数据到0x...58
- Foo析构函数在0x...18上被调用(使用f2数据)
- Foo析构函数也在0x...58上被调用(使用f2数据)
因此,对于相同的数据(f2),Foo析构函数会被调用两次。显然,我对内部的工作方式缺乏了解,所以有人能指导一下吗?
f
所持有的名称从“f1”更改为“f2”,因此您将不会看到“f1”析构函数的消息。 因此,您会先看到临时的“f2”被析构,然后才是原始实例(现在命名为“f2”)被析构。请注意,数据不同,它是具有相同值的副本。 - Peter Huene