关于“编译器会生成默认的构造函数”之剖析

开篇先列一下本篇文章要解释的几个知识点

背景:我们知道,如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数。

本节剖析:

(1)如果没有显式定义,编译器真的会生成默认构造函数吗?

(2)在什么场景下,编译器会生成默认构造函数,什么场景下不会?


以一个简单的日期类来探索今天的主题

例1:

class Date
{
public:

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	
	Date d;
	return 0;
}

编译成功。我们并没有有显式地给出构造函数,但是对象也创建成功,所以。可以猜想:是编译器合成了一个默认构造函数。

例2:

class Time
{
public:

	Time()
	{
		cout << "time()" << endl;
	}
	Time(int hour=1 , int minute = 1, int second = 1)
	{
		cout << "time()" << endl;
		_hour = hour;
		_minute = minute;
		_second = second;
	}
private:
	int _hour;
	int _minute;
	int _second;

};

class Date
{
public:

private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	Date d;//Date::
	return 0;
}

如上:在上述的代码中,我们定义了两个类,Time类和Date类,其中,Date类中包含有一个Time类的成员。此外在Time类中显式地给出了构造函数,而Date类中则没有。

我们在主函数中创建了对象d,是Date类的,然而对象d当中还有Time _t成员,那么d对象的又是怎么创建的呢?首先可以肯定对于_t的创建肯定是要调用Time类的构造函数的,那么究竟在什么时机调用?肯定不可能直接调用,因为d对象是Date类型,要调用也应该是调用Date类的构造函数。所以我们的猜想是:编译器默认生成了Date类的构造函数,调用的是Date类的构造函数。这里可以在Date d;处打断点,然后看汇编代码。

通过查看汇编代码,发现编译器默认生成了Date类的构造函数。先调用的是Date类的构造函数,然后在Date类的构造函数中调用了Time类的构造函数。

以上两个例子,看似证明了开篇所提的“背景”---如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数

 


下面我们做一个更深的剖析

还是上面的例1:

class Date
{
public:

private:
	int _year;
	int _month;
	int _day;
};

int main()
{

	Date d;//Date::
	return 0;
}

同样,这里我们在Date d处打断点,查看一下汇编,看有没有调用Date构造函数

怎么样?是不是很诧异?不符合语法啊,明明我们一直学的都是“如果类中没有显式定义构造函数,则编译器会自动生成一个无参的默认构造函数”。其实不然,虽然语法层面是这样说的,但是通过代码验证,我们可以看出,实际上编译器会根据需要进行优化。总结起来就是--->

语法:如果一个类没有显式定义任何构造函数,编译器将会生成一个默认的构造函数

实际:编译器关于是否生成构造函数会进行优化,如果编译器觉得需要才会生成

对于例2:(Date类中没有显式定义构造函数,Time类中显式定义无参构造函数)

class Time
{
public:

	Time()//在Time类中显式定义一个无参的构造函数
	{
		cout << "time()" << endl;
	}
private:
	int _hour;
	int _minute;
	int _second;

};

class Date
{
public:
private:
	int _year;
	int _month;
	int _day;
	Time _t;//Date类中包含有一个Time类型的成员
};

int main()
{
	
	Date d;
	return 0;
}

查看汇编,发现编译器生成了默认的Date构造函数,与最开始的例2结果一致。

代码稍作改动,这次在Time类中不显式给出构造函数,Date类中也不给出,观察编译器是否会生成默认的

class Time
{
public:
	
private:
	int _hour;
	int _minute;
	int _second;

};

class Date
{
public:
	
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

int main()
{
	
	Date d;
	return 0;
}

可以看到,不会生成默认的Date类构造函数。


总结:

 

 

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页