首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >直接初始化空初始化程序列表

直接初始化空初始化程序列表
EN

Stack Overflow用户
提问于 2018-02-05 07:33:02
回答 2查看 6.3K关注 0票数 11
代码语言:javascript
复制
struct X
{
    X() { std::cout << "default ctor" << std::endl; }

};

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

这个打印出来

代码语言:javascript
复制
default ctor

这是有意义的,因为空大括号值-初始化对象(我认为)。然而,

代码语言:javascript
复制
struct X
{
    X() { std::cout << "default ctor" << std::endl; }
    X(std::initializer_list<int>) { std::cout << "initializer list" << std::endl; }
};

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

为了这个,我有

代码语言:javascript
复制
initializer list

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

这种行为是否写入了标准的某个部分?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-05 07:39:42

这种行为是否写入了标准的某个部分?

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

初始化器的语义如下。目标类型是正在初始化的对象或引用的类型,源类型是初始化器表达式的类型。如果初始化器不是单个(可能是括号大小)表达式,则不定义源类型。

  • 如果初始化器是(non-parenthesized)大括号-init-列表,则对象或引用是列表初始化(dcl.init.list)。
  • ..。
  • 如果目标类型是(可能是cv限定的)类类型:
代码语言:javascript
复制
- **If the initialization is direct-initialization**, or if it is copy-initialization where the cv-unqualified version of the source   type is the same class as, or a derived class of, the class of the   destination, **constructors are considered**. The applicable constructors   are enumerated ([over.match.ctor]), and the best one is chosen through   overload resolution ([over.match]). The constructor so selected is   called to initialize the object, with the initializer expression or   expression-list as its argument(s). If no constructor applies, or the   overload resolution is ambiguous, the initialization is ill-formed.
- [...]

您提供一个括号大小的空大括号-init-列表,所以只适用于后一个项目。考虑构造函数,在第一种情况下,我们将从默认初始化的X执行副本初始化。在后一种情况下,选择initializer_list C‘’tor作为更好的匹配。选择此重载的规则在[over.ics.list]中指定。

当参数是初始化程序列表(dcl.init.list)时,它不是表达式,并且适用于将其转换为参数类型的特殊规则。 如果参数类型为std::initializer_list或“X数组”,并且初始化程序列表的所有元素都可以隐式转换为X,则隐式转换序列是将列表中的元素转换为X所必需的最差转换。即使在调用初始化程序列表构造函数的上下文中,这种转换也可以是用户定义的转换。 否则,如果参数是非聚合类X,并且每个over.match.list都选择一个最佳的X构造函数来从参数初始化程序列表中执行X类型对象的初始化,则隐式转换序列是用户定义的转换序列。如果多个构造函数是可行的,但没有比其他构造函数更好的,则隐式转换序列就是模糊转换序列。用户定义的转换被允许将初始化器列表元素转换为构造函数参数类型,除非在over.best.ics中有说明。

票数 9
EN

Stack Overflow用户

发布于 2018-02-05 07:59:58

要了解实际情况,请声明复制和移动构造函数,以C++14模式或更早的模式编译,并禁用复制省略。

Coliru链接

输出:

代码语言:javascript
复制
default ctor
move ctor

在第一个片段中,编译器查找接受单个参数的X的构造函数,因为您提供了一个参数。这些是复制和移动构造函数X::X(const X&)X::X(X&&),如果您不自己声明它们,编译器将为您隐式声明它们。然后,编译器使用默认构造函数将{}转换为X对象,并将该X对象传递给移动构造函数。(您必须使用fno-elide-constructors来查看这一点,否则编译器将删除该移动,并且在C++17中,复制省略成为必需的。)

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

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48617690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档