我有以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
当我启动程序(vs2008,调试)时,我有以下输出:
x:0
y:0
--------
x:-858993460
y:-858993460
--------
Run Code Online (Sandbox Code Playgroud)
如您所见,b1.x和b1.y的值为0.为什么?init1和init2有什么区别?
当我取消注释B构造函数时,我有以下输出:
x:-858993460
y:-858993460
--------
x:-858993460
y:-858993460
--------
Run Code Online (Sandbox Code Playgroud)
有人可以解释这种行为的原因吗?Tnx提前.
Kir*_*sky 10
POD类型的默认构造函数用零填充它.当您明确定义自己的构造函数时,您不会初始化x并且y您将获得随机值(在VS调试中,它们将填充精确值,但在发布时它们将是随机的).
它符合C++ 03标准8.5/5:
<...> 对类型为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 = {};.
在这两种情况下,这条语句定义B1和复制intializes从它的值初始化临时B对象.
B b1 = B();
Run Code Online (Sandbox Code Playgroud)
当B没有用户声明的构造函数时,值初始化会导致调用B成员的值为初始值,对于简单类型,例如int,这意味着零初始化.
什么B时候有用户声明的构造函数,value-initializing尝试调用默认构造函数.如果成员x并y没有在构造函数初始化列表中列出,那么它们将保持未初始化状态.
B b2;
Run Code Online (Sandbox Code Playgroud)
在函数中,没有初始化器的POD类型的本地对象保持未初始化.当您没有为其定义构造函数时B,它是一个POD类,因此这适用,并且值的值b2.x和b2.y不确定值.
如果对象是非POD类类型,那么它是默认初始化的,但是如果它调用一个构造函数,使其成员保持未初始化状态,那么这没有区别.