偶然发现,有人可以解释这里发生了什么吗?
struct Foo {
int i;
~Foo() {
std::cout << i << std::endl;
}
};
void bar()
{
Foo f;
f.i = 1;
f = Foo();
f.i = 2;
}
我得到以下输出:
-85899... (gibberish = "default" value for uninitialized int)
2
我期待的地方
1
2
为什么f.i = 1;
似乎没有效果?
答案 0 :(得分:11)
因此,在第一次调用析构函数时被销毁的变量不是f
,而是Foo()
创建的临时变量。由于您没有构造函数,i
具有不确定的值。如果你要添加一个将i
设置为99999的构造函数,那么你会看到析构函数的输出。
void bar()
{
Foo f; // Construct f of type Foo
f.i = 1; // Set i to 1 in f.
f = Foo(); // Construct a temporary Foo object, copy it to f,
// then destroy the temporary object.
f.i = 2; // Set the newly copied f.i to 2.
// destroy f.
}
答案 1 :(得分:9)
f.i = 1
确实有效。它将成员i
设置为等于1
。你只会看到如果对象被销毁,因为你在析构函数中输出了值。
在第f = Foo();
行中,您正在创建一个临时Foo
对象,其中i
具有不确定的值,然后将其分配给对象f
。该临时对象在该行的末尾被销毁,并将其打印为自己的不确定i
。这就是为您提供-85899...
输出的原因。
将不确定值复制到对象f
,然后用值i
覆盖其成员2
。在bar
结束时,此对象将被销毁,您会看到输出2
。
答案 2 :(得分:4)
这样:
f = Foo();
创建一个新对象,然后复制它。然后这个对象在这一行结束时受到了压力,但它根本没有被初始化。刚复制过。
答案 3 :(得分:2)
第一个输出是来自临时调用的析构函数。默认赋值运算符不会调用任何析构函数,因此永远不会调用将打印1
的析构函数。
一些代码来说明:
struct Foo {
int i;
// we emulate the default operator= generated by the compiler
// no check for self-assignment
Foo& operator=(const Foo& other) { this->i = other.i; }
};
void bar() {
F f;
f.i = 1;
f = Foo(); // the i member of the temporary is indeterminate
// now f.i is indeterminate
// destroy the temporary
f.i = 2;
} // end of scope, destroy f