Bjarne写道: -
对于类型T,T()是默认值的表示法,由默认构造函数定义。
当我们不声明默认构造函数时会发生什么?例如
using namespace std;
class date{
int n,m;
public:
int day(){return n;}
int month(){return m;}
};//no default constructor
int main()
{
date any =date();
cout<<any.month()<<endl;
cout<<any.day()<<endl;
return 0;
}
每次运行程序时,此程序的输出为0和0。我没有声明任何默认构造函数然后为什么会退出默认值,即0?
编辑 -
class date{
int n,m;
public:
date (){
m=1;}
int day(){return n;}
int month(){return m;}
};
int main()
{
date any =date();
cout<<any.month()<<endl;
cout<<any.day()<<endl;
return 0;
}
在阅读答案后,我提供了一个默认构造函数,但是现在n正在获取垃圾值但是根据答案它应该是0,因为m是任何其他构造函数都无法接触的,并且它是值初始化,如答案中所述
答案 0 :(得分:5)
您看到的行为是为您的班级定义的。
如何&amp;为什么行为定义明确?
规则是:
如果您没有提供无参数构造函数,则编译器会为您的程序生成一个,以防您的程序需要一个
的警告:强>
如果程序为类定义了任何构造函数,则编译器不会生成无参数构造函数。
根据C ++标准,可以通过3种方式初始化对象:
当类型名称或构造函数初始值设定项后跟()
时,初始化是通过值初始化。
因此,
date any =date();
^^^
值初始化无名对象,然后将其复制到本地对象any
,
while:
date any;
将是默认初始化。
值初始化为任何构造函数不可及的成员提供初始值零
在您的计划中,n
和m
超出了任何构造函数的范围,因此会初始化为0
。
回答编辑问题:
在您编辑的案例中,您的类提供了无参数构造函数date()
,它能够(并且应该)初始化成员n
和m
,但此构造函数不会初始化两个成员,所以在这种情况下,没有进行零初始化,并且对象中的未初始化成员具有 Indeterminate (任意随机)值,此外该临时对象被复制到any
对象它显示节目不确定的成员值。
对于Standerdese粉丝:
对象初始化的规则适当地定义在:
C ++ 03标准8.5 / 5:
零初始化 T类型的对象意味着:
- 如果T是标量类型(3.9),则将对象设置为0(零)转换为T的值;
- 如果T是非联合类类型,则每个非静态数据成员和每个基类子对象都是零初始化的;
- 如果T是联合类型,则对象的第一个命名数据成员为零初始化;
- 如果T是数组类型,则每个元素都是零初始化的;
- 如果T是引用类型,则不执行初始化。要默认初始化,T类型的对象意味着:
- 如果T是非POD类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式错误);
- 如果T是数组类型,则每个元素都是默认初始化的;
- 否则,对象被零初始化。要值初始化 T类型的对象意味着:
- 如果T是具有用户声明的构造函数(12.1)的类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
- 如果T是没有用户声明的构造函数的非联合类类型,则T的每个非静态数据成员和基类组件都是值初始化的;
- 如果T是数组类型,则每个元素都是值初始化的;
- 否则,对象是零初始化
答案 1 :(得分:4)
因为诅咒的编译器会为你生成一个。
编辑:由于Als说它没有回答问题,我会详细说明。使用date any = date();
时,可以调用编译器生成的默认构造函数。此构造函数为所有基类和数据成员调用默认构造函数。对于您的数据成员int
,默认构造函数为int()
,将值设置为0
。这是code on ideone.com
#include <iostream>
int main( void )
{
int i = -123;
i = int();
std::cout << i << std::endl;
return( 0 );
}
节目输出:
0
答案 2 :(得分:0)
根据C ++标准草案(1996年12月工作文件):
如果类X没有用户声明的构造函数,则隐式声明默认构造函数。隐式声明的默认构造函数是其类的内联公共成员。