繁体   English   中英

使用空的初始化程序列表直接初始化

[英]Direct initialization with empty initializer list

struct X
{
    X() { std::cout << "default ctor" << std::endl; }

};

int main()
{
    X({});
}

打印出来

default ctor

这是有道理的,因为空括号值会初始化对象(我认为)。 然而,

struct X
{
    X() { std::cout << "default ctor" << std::endl; }
    X(std::initializer_list<int>) { std::cout << "initializer list" << std::endl; }
};

int main()
{
    X({});
}

为此,我得到了

initializer list

我觉得这种行为并不奇怪,但我并不完全相信。 这有什么规则?

此行为是否写在标准的某些部分中?

要了解实际情况,请声明复制并移动构造函数,在C ++ 14模式或更早的版本下进行编译,并禁用复制省略功能。

Coliru连结

输出:

default ctor
move ctor

在第一个代码段中,编译器将查找采用单个参数的X构造函数,因为您已经提供了单个参数。 这些是复制和移动构造函数X::X(const X&)X::X(X&&) ,如果您自己没有声明它们,则编译器将为您隐式声明它们。 然后,编译器使用默认构造函数将{}转换为X对象,并将该X对象传递给move构造函数。 (您必须使用fno-elide-constructors来查看此内容,否则编译器将忽略此举,并且在C ++ 17中必须执行复制省略。)

在第二个片段中,编译器现在可以选择将{}转换为X (然后调用move构造函数),或者将{}转换为std::initializer_list<int> (然后调用初始化程序列表构造函数)。 根据[over.ics.list] /6.2,从{}X的转换{}称为默认构造函数)是用户定义的转换,而根据[over.ics.list] / 4,则从{}std::initializer_list<int>是身份转换。 身份转换比用户定义的转换要好,因此编译器将调用初始化程序列表构造函数。

此行为是否写在标准的某些部分中?

当然。 所有这些都由[dcl.init] / 16中的规则决定,强调我的内容以匹配您的初始化程序:

初始化程序的语义如下。 目标类型是要初始化的对象或引用的类型,源类型是初始化器表达式的类型。 如果初始化程序不是单个(可能带有括号)表达式,则不会定义源类型。

  • 如果初始化程序是一个( 非括号括起来的 )braced-init-list,则该对象或引用将进行列表初始化([dcl.init.list])。

  • [...]

  • 如果目标类型是(可能是cv限定的)类类型:

    • 如果初始化是直接初始化 ,或者是复制初始化,其中源类型的cv不合格版本与目标的类相同,或者是该类的派生类, 则考虑构造函数 枚举适用的构造函数([over.match.ctor]),并通过重载分辨率([over.match])选择最佳的构造函数。 如此选择的构造函数将以初始化器表达式或expression-list作为其自变量来初始化对象。 如果没有构造函数适用,或者重载解决方案不明确,则初始化格式错误。
    • [...]

您提供了一个带括号的空括号初始列表,因此仅适用于后面的项目符号。 考虑构造函数,在第一种情况下,我们最终从默认的初始化X进行了复制初始化。 在后一种情况下,将initializer_list c'tor选择为更好的匹配。 选择此重载的规则在[over.ics.list]中指定:

当参数是初始化程序列表([dcl.init.list])时,它不是表达式,并且特殊规则适用于将其转换为参数类型。

如果参数类型为std :: initializer_list或“ X的数组”,并且初始化列表的所有元素都可以隐式转换为X,则隐式转换序列是将列表的元素转换为X所需的最差转换。即使在调用initializer-list构造函数的上下文中,转换也可以是用户定义的转换。

否则,如果参数是非聚合类X,并且每个[over.match.list]的重载分辨率都从参数初始值设定项列表中选择一个最佳的X构造函数来执行类型X对象的初始化,则隐式转换序列是用户定义的转换序列。 如果多个构造函数可行,但没有一个比其他构造函数更好,则隐式转换序列就是模棱两可的转换序列。 除非[over.best.ics]中有说明,否则允许用户定义的转换将初始化列表元素转换为构造函数参数类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM