在 C++11 之前,我们可以通过编写类似的代码来进行复制初始化A a = 1;
这或多或少相当于A a = A(1);
。也就是说,首先创建一个临时对象,然后调用一个复制构造函数。不管复制省略如何,这在概念上都必须是这样,并且复制者必须是可访问的。
通过 C++11 中的列表初始化,我们可以通过编写来进行复制列表初始化A a = {1, 2};
。在我看来,这应该或多或少相当于A a = A(1, 2);
。然而,在 GCC 和 clang 上,A a = {1, 2}
即使复制和移动构造函数无法访问(通过声明为私有),也会进行编译。仍然,A a = 1;
如果相应的复制/移动向量无法访问,则不会在 GCC 或 clang 上编译。所以,A a = {1, 2};
似乎或多或少相当于A a{1, 2};
这是直接列表初始化。这和真正的直接列表初始化的区别在于A a = {1, 2};
如果采用两个 int 的 ctor 是显式的,则不会编译。在这方面,A a = {1, 2};
类似于复制初始化。
所以,我的问题是:表达式的确切语义是什么A a = {1, 2};
从概念上讲?经过概念上、复制省略不要妨碍。
该标准很好地描述了这一点; [dcl.init.list]/3:
对象或类型引用的列表初始化T
定义如下:
- [...]
- 否则,如果
T
是类类型,则考虑构造函数。这
枚举适用的构造函数并选择最好的构造函数
通过重载决议(13.3、13.3.1.7)。如果收窄
转换任何参数都需要转换(见下文),
该程序格式不正确。
[over.match.list](强调我的):
当非聚合类类型的对象T
是列表初始化的
(8.5.4),重载决策分两个阶段选择构造函数:
如果初始值设定项列表没有
elements 和 T 有一个默认构造函数,第一阶段被省略。
在复制列表初始化中,如果explicit
选择构造函数后,
初始化格式不正确。
因此,如果没有找到初始值设定项列表构造函数(如您的情况),则初始值设定项列表的元素构成构造函数调用的参数。
事实上,only最后一个粗体句子涵盖了直接列表初始化和复制列表初始化的区别。
这是列表初始化的优点之一:它不需要存在无论如何都不会使用的特殊成员函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)