复制列表初始化在概念上调用copy ctor吗? [英] Does copy list initialization invoke copy ctor conceptually?
问题描述
在C ++ 11之前,我们可以通过编写类似 A a = 1;
的复制初始化,它大致等同于 A a = A(1);
。也就是说,首先创建临时,然后调用复制ctor。无论复制精度如何,这必须是概念上的,并且复制ctor必须可访问。
在C ++ 11中的列表初始化时,我们可以通过写 A a = {1,2};
。在我看来,这应该或多或少等价于 A a = A(1,2);
。然而,在GCC和clang, A a = {1,2}
编译,即使复制和移动ctor不可访问(通过声明为私有)。仍然, A a = 1;
不能在GCC或clang上编译,如果相应的副本/移动ctor不可访问。所以, 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)选择
。如果需要缩小
转换(见下文)以转换任何参数,
程序就会生成错误。
< blockquote>
[over.match.list](强调我的):
非聚合类类型
T
是列表初始化的
(8.5.4),重载解析选择两个阶段的构造函数:
最初,候选函数是T
类的初始化列表构造函数(8.5.4)。
如果没有找到可行的初始化列表构造函数, overload再次执行分辨率,其中候选函数都是
类T
的构造函数,并且参数列表由初始化器列表的
元素组成
如果初始化器列表没有
元素,T有一个默认构造函数,
在复制列表初始化中,如果选择了一个显式
构造函数,则
初始化为
因此,如果没有找到初始化列表构造函数的初始化器列表构成了构造函数调用的参数。
事实上,最后一个粗体字覆盖了直接列表初始化和复制列表初始化的区别。
这是列表初始化的优点之一:它不需要存在一个特殊的成员函数,不会使用。
Before C++11, we can do copy initialization by writing something like
A a = 1;
which is more or less equivalent toA a = A(1);
. That is, a temporary is first created and then a copy ctor is invoked. Regardless of copy elision, this must be so conceptually and the copy ctor must be accessible.With list initialization in C++11, we can do a copy list initialization by writing
A a = {1, 2};
. In my opinion, this should be more or less equivalent toA a = A(1, 2);
. However, on GCC and clang,A a = {1, 2}
compiles even when the copy and move ctor are inaccessible (by declaring as private). Still,A a = 1;
does not compile on GCC or clang if the corresponding copy/move ctor is inaccessible. So,A a = {1, 2};
seems more or less equivalent toA a{1, 2};
which is direct list initialization. The difference between this and the real direct list initialization is thatA a = {1, 2};
does not compile if the ctor that takes two ints are explicit. In this aspect,A a = {1, 2};
resembles copy initialization.So, my question is: what is the exact semantics of expressions like
A a = {1, 2};
conceptually? By conceptually, copy elision do not stay in the way.解决方案The standard describes it pretty well; [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] (emphasis mine):
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 class
T
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.Hence, if no initializer-list constructor is found (as in your case), the elements of the initializer list constitute the arguments for the constructor call.
In fact, the only difference of direct-list-initialization and copy-list-initialization is covered by the last, bolded sentence.This is one of the advantages of list-initialization: It doesn't necessitate the presence of a special member function that is not gonna be used anyway.
这篇关于复制列表初始化在概念上调用copy ctor吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!