两种调用默认构造函数的方法

时间:2009-10-09 09:53:42

标签: c++ constructor

我有以下代码:

struct B
{
 //B() {}
 int x;
 int y;
};

void print(const B &b) 
{
 std::cout<<"x:"<<b.x<<std::endl;
 std::cout<<"y:"<<b.y<<std::endl;
 std::cout<<"--------"<<std::endl;
}

int main()
{
 B b1 = B(); //init1
 B b2; //init2

 print(b1);
 print(b2);

 return 0;
}

当我启动程序(vs2008,debug)时,我有以下输出:

x:0
y:0
--------
x:-858993460
y:-858993460
--------

正如您所见,b1.x和b1.y的值为0。为什么? init1和init2之间有什么区别?

当我取消注释B构造函数时,我有以下输出:

x:-858993460
y:-858993460
--------
x:-858993460
y:-858993460
--------

有人可以解释这种行为的原因吗? Tnx提前。

5 个答案:

答案 0 :(得分:10)

POD类型的默认构造函数用零填充它。当您明确定义自己的构造函数时,您不会初始化xy并且您将获得随机值(在VS调试中,它们将填充精确值,但在发布时它们将是随机的)。 / p>

符合C ++ 03标准8.5 / 5:

  

&lt; ...&gt;要值初始化 T类型的对象意味着:
   - 如果T是具有用户声明的构造函数(12.1)的类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
   - 如果T是没有用户声明的构造函数的非联合类类型,则T的每个非静态数据成员和基类组件都是值初始化的;
   - 如果T是数组类型,则每个元素都是值初始化的;
   - 否则,对象零初始化

B()是临时值的初始化,将用于b1的复制初始化。

B b2中没有为对象指定初始值设定项,因此根据C ++ 03 Standard 8.5 / 9:

  

如果没有为对象指定初始化程序,并且该对象属于(可能是cv限定的)非POD类类型(或其数组),则该对象应默认初始化;如果对象是const限定类型,则底层类类型应具有用户声明的默认构造函数。 否则,如果没有为非静态对象指定初始值设定项,则该对象及其子对象(如果有)具有不确定的初始值;如果对象或其任何子对象是const限定类型,则程序格式不正确。

要为b2获取零,您可以写B b2 = {};

答案 1 :(得分:5)

在这两种情况下,此语句都是从值初始化的临时B对象中定义b1和 copy-intializes

B b1 = B();

B没有用户声明的构造函数时, value-initializing 会导致B成员的调用 value-initalized ,对于简单类型,例如int,这意味着零初始化

B具有用户声明的构造函数时, value-initializing 会尝试调用默认构造函数。如果成员xy未在构造函数初始值设定项列表中列出,则它们将保持未初始化状态。

B b2;

在函数中,没有初始化器的POD类型的本地对象未初始化。当您没有为B定义构造函数时,它是一个POD类,因此适用,b2.xb2.y的值具有不确定的值。

如果对象是非POD类类型,那么它是 default-initialized ,但是如果它调用的构造函数使其成员保持未初始化状态,那么这没有区别。

答案 2 :(得分:3)

这是值初始化而不是初始化。如果你写

B b1 = B();

你得到一个带有“value-initialized”临时值的复制初始化--B()。类类型对象的值初始化调用用户定义的构造函数(如果是existant)或以其他方式对成员进行值初始化。标量类型对象的值初始化等效于零初始化。当您声明自己没有做任何事情的构造函数时,您的标量成员不会被初始化。

B b1;

是默认初始化或根本没有初始化(取决于B)。

确切的初始化规则相当复杂。请参阅C ++标准第8.5节“初始化程序”。

答案 3 :(得分:2)

基尔的解释

另一个值:-858993460是0xCCCCCCCC,这是VC调试版本中未初始化堆栈内存的默认值。

未初始化的内存默认为0xCDCDCDCD。当然,在发布版本中,默认内容是随机的。

现在,我必须承认,我不知道直接调用c'tor是合法的,就像你的例子一样!而且我会发誓这是非法的......

答案 4 :(得分:0)

我试过vc6和Visual Studio 2005我得到了以下结果:你能否发布反汇编代码生成,如下所示我已经发布了2005年的反汇编代码

X:-858993460

Y:-858993460


X:-858993460

Y:-858993460


 B b1 = B(); //init1
0043DEDE  lea         ecx,[b1] 
0043DEE1  call        B::B (43ADD9h) 
 B b2; //init2
0043DEE6  lea         ecx,[b2] 
0043DEE9  call        B::B (43ADD9h) 

 print(b1);
0043DEEE  lea         eax,[b1] 
0043DEF1  push        eax  
0043DEF2  call        print (43A302h) 
0043DEF7  add         esp,4 
 print(b2);
0043DEFA  lea         eax,[b2] 
0043DEFD  push        eax  
0043DEFE  call        print (43A302h) 
0043DF03  add         esp,4