深入探索c++构造函数之一:默认构造函数与默认初始化

1、构造函数的基本概念
每个类都分别定义了它的对象被初始化的方式,类通过一个或者几个特殊的成员函数来控制其对象初始化的过程,这些函数叫构造函数
关于构造函数:
(1)作用:初始化对象的数据成员,只要对象创建就会被执行。
(2)返回值:无返回值
(3)参数:参数列表可以为空,函数体也可以为空
(4)构造函数重载:一个类可以包含多个构造函数,不同的构造函数之间必须在参数数量或者参数类型上有所区别。
(5)构造函数不能被声明为const的,同是当我们创建一个const对象时,只有当构造函数完成之后,对象才能真正取得常量属性。(不然,一开始就是常量怎么初始化呢?)

2、默认构造函数与合成的默认构造函数
当我们定义一个对象是,如果没有为这些对象提供初值,那么就会通过默认构造函数执行初始化默认构造函数无需任何实参

class Student
{
public:
    Student()   //显示定义一个默认构造函数
    {
        id=123;
    }
    Student(int ID):id(ID){}//有参数的构造函数
 private:
     int id;
};
  Student xiaoming;//定义一个对象,没有提供初始值,执行默认构造函数,即id=123

如果我们的类没有显示定义构造函数,那么编译器就我们隐式的定义一个构造函数,这个构造函数称为合成的默认构造函数。由合成的默认构造函数按照一定规则初始化对象。

class Student
{
public:
    //这一块没有显示定义构造函数
 private:
     int id;
};
  Student xiaoming;//定义一个对象,没有提供初始值,执行合成的默认构造函数进行初始化

3、合成的默认构造函数初始化规则
对于大多数类来说,这个合成的默认构造函数将按照一下规则来初始化数据成员:
如果存在类内的初始值,用它来初始化成员 (情形1)-std=c++11
否则,执行默认初始化 (情形2)

struct Sales_item
{
    std::string bookNo;
    unsigned char units_sold=0;//类内存在初始值
    double revenue=0;//类内存在初始值
};
Sales_item It;//执行合成的默认构造函数,类内初始值初始化(情形1)
//类内初始值初始化之后,It.units_sold=0, It.revenue=0

默认初始化规则:
………………非成员变量默认初始化规则(规则1)
如果变量是内置类型(int、double、char等)或者复合型(指针,数组),那么
定义于任何函数体外的内置型变量都会被初始化为0
定义于函数体内的内置型变量不被初始化

//内置类型初始化规则
#include <iostream>
using namespace std;
int i;              //函数体外,初始化为0
double d;           //函数体外,初始化为0
char *ptr;          //函数体外,初始化为0
int arr[3];         //函数体外,初始化为0
int main() {
	cout<<"i:"<<i<<"  d:"<<d<<endl;
	if(ptr==NULL)cout<<"ptr is NULL\n";
	for(int k=0;k<3;k++)
	cout<<arr[k]<<" ";
	cout<<endl;
	int jj;//********main函数体内定义,不被初始化,值是未确定的*****
	return 0;
}

内置型变量变量如果没有初始化,容易引发运行故障,一定要尽量避免,即在定义内执行变量的时候,尽可能的将其初始化。
………………类成员变量默认初始化规则(规则2)
类成员变量默认初始化规则与非成员变量初始化规则类似
对象中的内置类型成员变量按规则1初始化
对象中的成员变量若是类类型,则该成员变量按默认构造函数初始化

#include <iostream>
using namespace std;
class Test 
{
publicint i;
    double d;
    char *ptr;
}

Test inTest;//函数体外定义的对象,那么
//对象中的内置型成员变量初始化为0,即inTest.i=0,inTest.d=0,inTest.ptr=NULL
int main() {
	Test outTest;//函数体类定义的对象,那么内置型成员变量将不被初始化
	return 0;
}

注意:
默认初始化的前提就是执行合成的默认构造函数,即类没有显示定义构造函数。否则,如果类定义了默认构造函数(即使默认构造函数啥也不做),也不会进行默认初始化。
补充说明:
变量声明与变量定义的关系
声明:使得名字为程序所知,一个文件想要使用别处定义的名字则必须要包含对那个名字的声明。
定义:负责创建与名字关联的实体。(分配内存空间)
想要声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显示地初始化变量。

extern int i;//声明i,而非定义i
int j;//声明并定义j
extern double pi=3.1415;//定义

声明与定义的区别看起来微不足道,但是实际非常重要。如果多个文件想要使用同一个变量,那就必须将变量声明与定义分离。此时变量的定义必须出现在一个文件且只能出现在一个文件中,而其它用到该变量的文件必须对其进行声明,却绝对不能重复定义。
总之,变量能且只能被定义一次,但是可以有多次声明。

参考资料:
C++ Primer 中文版(第5版)
深度探索C++对象模型(侯捷译)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值