为什么标准区分直接列表初始化和复制列表初始化?

Xeo*_*Xeo 37 c++ language-lawyer c++11 list-initialization

我们知道这T v(x);被称为直接初始化,而T v = x;被称为复制初始化,这意味着它将构造一个临时Tx,将被复制/移入v(很可能被省略).

对于列表初始化,标准根据上下文区分两种形式.T v{x};称为直接列表初始化,T v = {x};称为复制列表初始化:

§8.5.4 [dcl.init.list] p1

[...]列表初始化可以在直接初始化或复制初始化上下文中进行; 直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化.[...]

但是,整个标准中只有两个引用.对于直接列表初始化,在创建像T{x}(§5.2.3/3)这样的临时表时会提到它.对于copy-list-initialization,它用于返回语句中的表达式,如return {x};(§6.6.3/2).

现在,下面的片段怎么样?

#include <initializer_list>

struct X{
  X(X const&) = delete; // no copy
  X(X&&) = delete; // no move
  X(std::initializer_list<int>){} // only list-init from 'int's
};

int main(){
  X x = {42};
}
Run Code Online (Sandbox Code Playgroud)

通常,从X x = expr;模式中,我们期望代码无法编译,因为移动构造函数X定义为deleted.但是,最新版本的Clang和GCC编译上面的代码就好了,经过挖掘(并找到上面的引用)后,这似乎是正确的行为.标准只定义了整个列表初始化的行为,除了上面提到的点之外,根本不区分这两种形式.好吧,至少我可以看到,无论如何.

那么,再次总结一下我的问题:

如果它们(显然)执行完全相同的事情,将列表初始化拆分为两种形式有什么用?

Nic*_*las 33

因为他们没有做同样的事情.如13.3.1.7 [over.match.list]中所述:

在copy-list-initialization中,如果选择了显式构造函数,则初始化是错误的.

简而言之,您只能在复制列表初始化上下文中使用隐式转换.

这是明确添加的,以使统一初始化不是,嗯,统一.是的,我知道这听起来多么愚蠢,但请耐心等待.

2008年,N2640发布(PDF),看看统一初始化的当前状态.它特别注意了direct initialization(T{...})和copy-initialization(T = {...})之间的区别.

总而言之,关注的是explicit构造者实际上会变得毫无意义.如果我有一些T我希望能够从整数构造的类型,但我不想隐式转换,我将构造函数标记为显式.

然后有人这样做:

T func()
{
  return {1};
}
Run Code Online (Sandbox Code Playgroud)

如果没有当前的措辞,这将调用我的explicit构造函数.那么explicit如果构造函数没有太大变化,它有什么用呢?

使用当前的措辞,您至少需要直接使用该名称:

T func()
{
  return T{1};
}
Run Code Online (Sandbox Code Playgroud)

  • @jpalecek:从第13.3.1.7节开始,p1:` - 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成. - 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化列表的元素组成.所以你必须看一个旧版本的标准(我无法在任何地方找到该声明). (7认同)
  • 我应该知道这一点,因为我经常抱怨`std :: tuple`和`std :: unique_ptr的构造函数是`explicit`所以我不能做`return {a,b,c};`.:) (3认同)
  • @jpalecek我认为这是一个gcc4.5.1错误,因为[this](https://ideone.com/irZBfk)编译在4.7.0上.`b`正在通过(编译器生成的)复制构造函数初始化,并且未选择构造函数`initializer_list`,即使它是首选的,因为braced-init-list的成员不能转换为` int`.正如Nicol在之前的评论中所说,如果存在一个`A :: A(initializer_list <A>)`构造函数,那么将在复制构造函数中选择它. (3认同)