C++ 为什么这个成员变量没有正确初始化?

C++ 为什么这个成员变量没有正确初始化?,c++,C++,偶然发现了这个,有人能解释这里发生了什么吗 struct Foo { int i; ~Foo() { std::cout << i << std::endl; } }; void bar() { Foo f; f.i = 1; f = Foo(); f.i = 2; } 在我期待的地方 1 2 为什么f.i=1;这里似乎没有效果?因此,在第一次调用析构函数时销毁的变量不是f,而是Foo创建的临时

偶然发现了这个,有人能解释这里发生了什么吗

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

void bar()
{
    Foo f;
    f.i = 1;
    f = Foo();
    f.i = 2;
}
在我期待的地方

1
2

为什么f.i=1;这里似乎没有效果?

因此,在第一次调用析构函数时销毁的变量不是f,而是Foo创建的临时变量。因为没有构造函数,所以我有一个不确定的值。如果您要添加一个将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.
}

因此,在第一次调用析构函数时销毁的变量不是f,而是Foo创建的临时变量。因为没有构造函数,所以我有一个不确定的值。如果您要添加一个将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.
}
这:

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

此:

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

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

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

不确定值被复制到对象f,但随后用值2覆盖其成员i。在条形图的末尾,该对象被销毁,您将看到输出2。

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

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


不确定值被复制到对象f,但随后用值2覆盖其成员i。在条形图的末尾,这个对象被销毁,您将看到输出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

第一个输出来自临时调用的析构函数。默认赋值运算符不调用任何析构函数,因此不会调用将打印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


因为当你给f赋值时,f的析构函数不会被调用。第一个输出可能来自f=Foo中临时的析构函数。@mfontani没有未定义的行为。未初始化时i的值是不确定的。行为是有定义的,但不是确定的。两件完全不同的事情。你使用的是古老的编译器吗?从2003年甚至1998年开始,Foo应该初始化临时值,将i设置为0。@MikeSeymour我正在使用VC10。@Niko:所以它是有缺陷的,而不是古老的。因为当你给f赋值时,f的析构函数不会被调用。第一个输出可能来自f=Foo中临时的析构函数。@mfontani没有未定义的行为。未初始化时i的值是不确定的。行为是有定义的,但不是确定的。两件完全不同的事情。你使用的是古老的编译器吗?从2003年甚至1998年开始,Foo应该初始化临时值,将i设置为0。@MikeSeymour我正在使用VC10。@Niko:所以它是有缺陷的,而不是古老的。第二行是因为什么?@Niko-在你的作用域/程序末尾的f的析构函数。第二行是因为什么?@Niko-在你的作用域/程序末尾的f的析构函数。我认为关于这段代码,没有什么可以说的了+可能值得一提的是,一个合理的现代、非BGGY编译器应该重视临时和打印零,而不是垃圾。@ MikEyMyC++将永远不会用简单类型来初始化初始化成员变量,除非您告诉它。这是设计-值初始化它们需要时间,C++假设你不关心,不想浪费时间除非你告诉它否则。特别是,该值被认为是不确定的。@EdwardLoper:不,通过编写Foo,您告诉它初始化临时值,从而初始化其成员。没有办法创建一个默认的初始化临时文件。@MikeSeymour是的,我没有注意到。对于其他任何对Mike的原因感兴趣的人
是的,请看:我不认为关于问题中的代码片段还有什么可说的了+可能值得一提的是,一个合理的现代、非BGGY编译器应该重视临时和打印零,而不是垃圾。@ MikEyMyC++将永远不会用简单类型来初始化初始化成员变量,除非您告诉它。这是设计-值初始化它们需要时间,C++假设你不关心,不想浪费时间除非你告诉它否则。特别是,该值被认为是不确定的。@EdwardLoper:不,通过编写Foo,您告诉它初始化临时值,从而初始化其成员。没有办法创建一个默认的初始化临时文件。@MikeSeymour是的,我没有注意到。对于其他任何对Mike的正确性细节感兴趣的人,请参见: