1

Just stumbled on this, can anybody explain what is happening here?

struct Foo {
    int i;
    ~Foo() {
        std::cout << i << std::endl;
    }
};

void bar()
{
    Foo f;
    f.i = 1;
    f = Foo();
    f.i = 2;
}

I'm getting the following output:

-85899... (gibberish = "default" value for uninitialized int)
2

where I expected

1
2

Why is it that f.i = 1; seems to have no effect here?

4

4 回答 4

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.
}
于 2013-05-10T12:46:44.297 回答
9

f.i = 1确实有效果。它将成员i设置为等于1。您只会看到对象被销毁的情况,因为您在析构函数中输出值。

在该行f = Foo();中,您正在创建一个临时Foo对象,该对象i具有不确定的值,然后将其分配给该对象f。这个临时对象在行尾被销毁,打印它自己的 indeterminate i。这就是为您提供-85899...输出的原因。

不确定的值被复制到对象f中,但随后您i用该值覆盖了它的成员2。最后bar,这个对象被销毁,你会看到输出2

于 2013-05-10T12:47:13.733 回答
4

这个:

f = Foo();

创建一个新对象,然后复制它。然后这个对象在这一行的末尾被破坏了,但它根本没有被初始化。刚刚复制。

于 2013-05-10T12:46:59.047 回答
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
于 2013-05-10T12:47:29.137 回答