未定义构造函数的默认值

T.J*_*.J. 3 c++ constructor

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;

}
Run Code Online (Sandbox Code Playgroud)

每次运行程序时,该程序的输出为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;

}
Run Code Online (Sandbox Code Playgroud)

在阅读答案后,我提供了一个默认构造函数,但现在n正在获取垃圾值但是根据答案它应该是0,因为m是任何其他构造函数都无法接触的,并且它是值初始化,如答案中所述

Alo*_*ave 5

您看到的行为是为您的班级定义的.


如何以及为什么行为定义明确?

规则是:
如果您不提供无参数构造函数,则编译器会为您的程序生成一个,以防您的程序需要一个.
警告:
如果您的程序为该类定义了任何构造函数,则编译器不会生成无参数构造函数.

根据C++标准,可以通过3种方式初始化对象:

  • 零初始化
  • 默认初始化&
  • 价值初始化

当,类型名称或构造函数初始化程序后面()的初始化是通过值初始化.

从而,

date any =date();
              ^^^
Run Code Online (Sandbox Code Playgroud)

值初始化无名对象,然后将其复制到本地对象any,同时:

date any;
Run Code Online (Sandbox Code Playgroud)

将是默认初始化.

值初始化为任何构造函数不可及的成员提供零的初始值.
在你的程序中,n并且m超出了任何构造函数的范围,因此被初始化为0.


回答编辑问题:
在你编辑的情况下,你的类提供了一个无参数的构造函数,date()它能够(n并且应该)初始化成员m,但是这个构造函数不会初始化这两个成员,所以在这种情况下不会发生零初始化,并且对象中的未初始化成员具有Indeterminate(任意随机)值,此外,此临时对象将复制到any对象,该对象显示show indeterminate成员值.


对于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是一个类型(第9节)与用户声明的构造(12.1),然后对T中的默认构造函数被调用(以及初始化是形成不良的如果T没有可访问的默认构造函数);
- 如果T是没有用户声明的构造函数的非联合类类型,则T的每个非静态数据成员和基类组件都是值初始化的;
- 如果T是数组类型,则每个元素都是值初始化的;
- 否则,对象被零初始化