c – 复制列表初始化是否从概念上调用了复制ctor?
作者:互联网
在C 11之前,我们可以通过写A a = 1之类的东西进行复制初始化.这或多或少等于A a = A(1);也就是说,首先创建临时,然后调用复制ctor.无论版本是否复制,这必须是概念上的,并且必须可以访问复制文件.
通过C 11中的列表初始化,我们可以通过写A a = {1,2};来进行复制列表初始化.在我看来,这应该或多或少等同于A a = A(1,2);.但是,在GCC和clang上,即使复制和移动ctor不可访问(通过声明为私有),A a = {1,2}也会编译. A a = 1;如果相应的复制/移动ctor不可访问,则不会在GCC或clang上编译.所以,A a = {1,2};似乎或多或少等同于A a {1,2};这是直接列表初始化.这和实际直接列表初始化之间的区别在于A a = {1,2};如果采用两个整数的ctor是明确的,则不会编译.在这方面,A a = {1,2};类似于复制初始化.
所以,我的问题是:A a = {1,2}等表达式的确切语义是什么?概念?从概念上讲,复制省略不会妨碍.
解决方法:
标准很好地描述了它; [dcl.init.list] / 3:
List-initialization of an object or reference of type
T
is defined as follows:
- […]
- Otherwise, if
T
is a class type, constructors are considered. The
applicable constructors are enumerated and the best one is chosen
through overload resolution (13.3, 13.3.1.7). If a narrowing
conversion (see below) is required to convert any of the arguments,
the program is ill-formed.
[over.match.list](强调我的):
When objects of non-aggregate class type
T
are list-initialized
(8.5.4), overload resolution selects the constructor in two phases:
Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class
T
and the argument list consists of
the initializer list as a single argument.If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all
the constructors of the classT
and the argument list consists of the
elements of the initializer list.If the initializer list has no
elements and T has a default constructor, the first phase is omitted.
In copy-list-initialization, if anexplicit
constructor is chosen, the
initialization is ill-formed.
因此,如果没有找到初始化列表构造函数(如您所示),则初始化列表的元素构成构造函数调用的参数.事实上,直接列表初始化和复制列表初始化的唯一区别在于最后一个粗体句子.
这是列表初始化的优点之一:它不需要存在无论如何都不会使用的特殊成员函数.
标签:list-initialization,c,c11,copy-constructor,copy-initialization 来源: https://codeday.me/bug/20191001/1837962.html