我试图理解在为堆栈上分配的对象分配新值时看起来有些奇怪的行为(对于相同的数据集,析构函数被调用两次)。我将从代码片段及其输出开始:
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
我期望发生的事情:
实际发生的事情:
所以最后, Foo析构函数被调用两次以获得相同的数据(f2)。很明显,我错过了一些关于内部如何运作的信息,那么有人可以指出我正确的方向吗?
答案 0 :(得分:4)
您的实例 f 被分配了一个副本的Foo {&#34; f2&#34;},它不是新< / em>建设。
添加以下 operator = 覆盖以说明实际发生的情况。
Foo& Foo::operator=(const Foo& other) {
cout << "Foo::operator=(const Foo& other)" << endl;
m_name = other.m_name;
return *this;
}
答案 1 :(得分:3)
在创建第二个Foo
对象之前,地址0x..58
只有一个对象。
Address: 0x..58 Data: { m_name "f1" }
Address: 0x..18 Data: unknown
第f = Foo {"f2"};
行首先创建一个m_name
值为"f2"
的新Foo对象,并将其存储在地址0x..18
。然后它将此对象分配给变量f
。
此赋值不会破坏f
中以前存在的对象,它只会将数据成员复制到其中。由于Foo对象只有一个数据成员m_name
,因此赋值只是将第二个对象的m_name
复制到第一个对象中。
Address: 0x..58 Data: { m_name "f2" }
Address: 0x..18 Data: { m_name "f2" }
然后为每个对象调用析构函数。输出并不意味着同一个对象被销毁两次,它只是意味着两个对象具有相同的m_name
。