C++11 中增加 default 关键字,本篇文章讲解下空实现的默认构造函数和 default 的默认构造函数的区别。
接下来,从以下几个方面来讲解 default 关键字:
- default 关键字使用示例
- default 和默认构造函数
以下代码运行环境为:win10 专业版 + vs2019 社区版。
1. default 关键字使用示例
请看下面的示例代码:
class Demo { public: Demo() = default; Demo(const Demo&) = default; Demo(Demo&&) = default; ~Demo() = default; Demo& operator=(const Demo&) = default; Demo& operator=(Demo&&) = default; // 以下场景不能使用 default // 1.有参非拷贝构造构造函数 // Demo(int) = default; 错误 // 2.普通成员函数 // void show() = default; 错误 };
2. default 和默认构造函数
当类的内部存在有参构造函数,此时,如果我们需要使用无参构造函数,就必须手动为类添加该构造函数。
添加无参构造函数的方式有两种,如下代码所示:
class Demo { public: // 第一种方式 Demo() {} // 第二种方式 Demo() = default; };
注意:两种形式的无参构造函数不能共存,此处仅为展示两种方式。
那么,这两种方式有什么区别呢?
第一种方式:当我们使用无参构造函数创建 Demo 类型对象时,由于无参构造函数显式存在,所以,必然会调用该无参构造函数。
请看下面的示例代码:
class Demo { public: Demo() {} }; void test() { Demo demo; }
第 9 行代码对应的汇编代码如下:
Demo demo; lea ecx,[demo] call Demo::Demo
虽然我们知道在第 9 行代码处调用一个空实现的无参构造函数除了增加开销,没有什么用途。但是,通过第 3 行汇编代码,我们看到此处仍然调用了 Demo 的构造函数。
第二种方式:当我们使用无参构造函数创建 Demo 类型对象时,由于使用 default 关键字,那么,无参构造函数是否显式添加就要取决于编译器是否需要。如果需要,则编译器会给我们增加一个无参构造函数,并进行调用。如果不需要,则不会添加无参构造函数。
请看下面的示例代码:
class Demo { public: Demo() = default; }; void test() { Demo demo; }
此时,第 9 行代码并没有调用任何的构造函数。
但是,当 Demo 类内部包含对象成员,并且对象成员包含默认构造函数时,编译器认为有必要调用 Demo 的无参构造函数,此时才会调用 Demo 的无参构造函数。请看下面的示例代码:
class Box { public: Box() {} }; class Demo { public: Demo() = default; public: Box box; }; void test() { Demo demo; }
第 17 行创建 demo 对象对应的汇编代码如下:
Demo demo; lea ecx,[demo] call Demo::Demo
从汇编代码来看,确实调用了 Demo 的无参构造函数。
为什么编译器认为有必要调用构造函数?以及哪些场景下会调用无参构造函数,请看文章:http://mengbaoliang.cn/?p=905
由此,我们得知,大部分场景下,可以使用 default 来代替一个具有空实现的构造函数会带来更好的效率。
至此,本文章内容结束,希望对你有所帮助!