C++中‘复制初始化语境下的默认初始化’指什么?
复制初始化语境下的默认初始化:到底是什么意思?
先给你把这个概念拆成两部分讲,先搞清楚语境,再看这种场景下的行为:
第一步:先明确两个基础语境的区别
你已经提到过int x{}(直接列表初始化)和int x = {}(复制列表初始化)的区别,其实类对象的初始化语境逻辑是类似的:
- 直接初始化:不用
=的初始化方式,比如MyClass obj;(默认初始化)、MyClass obj(10);、MyClass obj{};,这种语境下编译器会直接匹配对应的构造函数(默认构造、带参构造、列表构造等)。 - 复制初始化:用
=的初始化方式,比如MyClass obj = other_obj;、MyClass obj = MyClass(10);、MyClass obj = {};,这种语境下编译器会优先考虑转换构造函数(或者拷贝/移动构造)来完成初始化。
第二步:什么是“复制初始化语境下的默认初始化”?
这个场景指的就是:用复制初始化的语法(带=),但初始化器是空的(比如=后面跟{}),看起来像是要做默认初始化,但因为处于复制初始化的语境中,编译器的重载决议逻辑会和直接初始化语境下的默认初始化不一样。
举个具体的例子,你一看就懂:
#include <iostream> using namespace std; class Demo { public: // 无参默认构造函数 Demo() { cout << "调用无参默认构造" << endl; } // 带默认参数的转换构造函数(可以接受0个实参) Demo(int val = 0) { cout << "调用带默认参数的转换构造" << endl; } }; int main() { // 直接初始化语境下的默认初始化 Demo a; // 复制初始化语境下的默认初始化 Demo b = {}; return 0; }
运行这段代码,输出会是:
调用无参默认构造 调用带默认参数的转换构造
哦!看到区别了吧?Demo a;是直接默认初始化,编译器直接调用无参的默认构造;但Demo b = {};处于复制初始化语境,这时候编译器会把所有转换构造函数作为候选(包括带默认参数、能接受空实参的转换构造),所以会选中Demo(int val=0),而不是无参构造。
再看你提到的那段规则的实际意义
你看到的规则翻译成人话就是:
在两种场景下,编译器会把目标类的所有转换构造函数作为候选来匹配:
- 用同类/派生类对象复制初始化时(比如
MyClass obj = other_obj;),这时候候选还会包含拷贝/移动构造(它们属于同类转换的特殊构造); - 就是我们说的「复制初始化语境下的默认初始化」(比如
MyClass obj = {};),这时候初始化器是空的,编译器会找能接受空实参的转换构造函数来调用。
如果没有合适的转换构造函数,编译器才会退而求其次调用无参默认构造函数。比如下面这个例子:
class Demo { public: Demo() { cout << "调用无参默认构造" << endl; } }; int main() { Demo b = {}; // 没有转换构造,只能调用无参默认构造 return 0; }
这时候输出就是调用无参默认构造。
内容的提问来源于stack exchange,提问作者ledonter
相关产品推荐
相关产品推荐

