C++ 编译器是否隐含生成默认构造函数和默认复制构造函数的4种情况讨论

① 类内有自定义构造函数和自定义复制构造函数

  根据C++标准定义,如果程序已定义构造函数,默认情况下编译器就不再隐含生成默认构造函数。注意,这里的“构造函数”包括复制构造函数(因为复制构造函数也是构造函数的一种)。

  此时该类一共有2个构造函数:自定义构造函数和自定义复制构造函数。

② 类内有自定义构造函数,无任何复制构造函数

  根据C++标准定义,有自定义构造函数,则无默认构造函数;无自定义复制构造函数,则隐含生成默认复制构造函数。下面使用代码检验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

class A{
public:
int x;
A(int x_=0): x(x_){}
};

int main()
{
A a;
cout << a.x << endl;
A b(a); //这里调用了默认复制构造函数
cout << b.x << endl;

return 0;
}

代码能正确执行;

  类A中没用声明任何复制构造函数,但是可以执行A b(a);说明编译器隐含生成了默认复制构造函数(使用单步跟踪检验,确实如此)。

  此时该类一共有2个构造函数:自定义构造函数和默认复制构造函数。

③ 类内无任何构造函数,无任何复制构造函数

  根据C++标准定义,编译器应该隐含生成默认构造函数和默认复制构造函数。下面用代码检验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

class A{
public:
int x=0;/*注:可能在早期的C++版本中,类的数据成员不能在声明时进行初始化,
但是在C++11新标准下,类的数据成员可以在声明时进行初始化,但不建议,
因为这样做破坏了类的抽象性)*/
};

int main()
{
A a; //这里调用了默认构造函数
cout << a.x << endl;
A b(a); //这里调用了默认复制构造函数
cout << b.x << endl;

return 0;
}

代码能正确执行;

  注意到,类的数据成员x在声明时同时定义了初始值。可能在早期的C++版本中,类的数据成员不能在声明时进行初始化,但是在C++11新标准下,类的数据成员可以在声明时进行初始化,但不建议,因为这样做破坏了类的抽象性。

  此时该类一共有2个构造函数:默认构造函数和默认复制构造函数。

⭐④ 类内无任何构造函数,有自定义复制构造函数

  (情况④较为特殊,应重点注意)
  按照C++标准,编译器应该隐含生成默认构造函数,事实是否如此?下面用代码来检验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

class A{
public:
int x=0;
A(A &a){ }
};

int main()
{
A a; //编译器提示错误,错误信息:类A不存在默认构造函数
cout << a.x << endl;
A b(a); //这里调用了默认复制构造函数
cout << b.x << endl;

return 0;
}

  代码执行错误,编译器并没有隐含生成默认构造函数。

  此时该类一共有1个构造函数:自定义复制构造函数。

PS

  C++11新标准中,默认构造函数和默认复制构造函数的一些新特性


————————— 本文结束 感谢您的阅读 —————————
谢谢你请我喝咖啡ლↂ‿‿ↂლ(支付宝扫一扫即可领红包, 消费时可抵现! 你省钱, 我赚钱, 多谢支持~)