为什么此成员变量未正确初始化?

时间:2013-05-10 12:44:01

标签: c++

偶然发现,有人可以解释这里发生了什么吗?

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;似乎没有效果?

4 个答案:

答案 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