首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在§8.5 p17 (初始化器的语义)中是否缺少N3797的情况?

在§8.5 p17 (初始化器的语义)中是否缺少N3797的情况?
EN

Stack Overflow用户
提问于 2014-01-07 13:54:24
回答 2查看 510关注 0票数 9

用于合计

代码语言:javascript
复制
struct S{int i, j;};

声明S s({1, 2});S s({1});根据N3797§8.5 p16执行直接初始化:

窗体中发生的初始化。 (A);{a}; 在new表达式(5.3.4)、static_cast表达式(5.2.9)、函数表示法类型转换(5.2.3)以及基和成员初始化器(12.6.2)中,都称为直接初始化。

但第8.5条p17似乎并没有描述它们的特点:

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

  • 如果初始化器是(非括号大小的)大括号内列表,则对象或引用是列表初始化(8.5.4)。
  • 如果目标类型是引用类型,请参见8.5.3。
  • 如果目标类型是字符数组、char16_t数组、char32_t数组或wchar_t数组,而初始化器是字符串文本,请参见8.5.2。
  • 如果初始化器为(),则对象为值初始化.
  • 否则,如果目标类型是数组,则程序的格式不正确.
  • 如果目标类型是(可能是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 (13.3.1.3), and the best one is chosen through overload resolution (13.3). 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.
- Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified   version of the destination type. The temporary is a prvalue. The result of the call (which is the   temporary for the constructor case) is then used to direct-initialize, according to the rules above,   the object that is the destination of the copy-initialization. In certain cases, an implementation   is permitted to eliminate the copying inherent in this direct-initialization by constructing the   intermediate result directly into the object being initialized; see 12.2, 12.8.

  • 否则,如果源类型是(可能是cv限定的)类类型,则考虑转换函数。列举了适用的转换函数(13.3.1.5),并通过过载解析(13.3)选择了最佳转换函数。调用如此选择的用户定义转换,将初始化器表达式转换为正在初始化的对象。如果转换不能完成或不明确,初始化就不正确.
  • 否则,被初始化对象的初始值是初始化器表达式的(可能转换的)值。如果有必要,将使用标准转换(第4条)将初始化器表达式转换为目标类型的cv非限定版本;不考虑用户定义的转换。如果无法完成转换,则初始化格式不正确.注意:类型“cv1 T”的表达式可以独立于cv-限定符cv1和cv2初始化“cv2T”类型的对象。 int a;const int b= a;int c= b; -尾注

主题声明,S s({1, 2});S s({1});

  • 不是列表初始化,因为每个初始化器都是括号大小的大括号-init-列表。
  • 目标类型不是引用。
  • 一般来说,目标类型不是字符数组。
  • 初始化器不是()
  • 目标类型不是数组。
EN

回答 2

Stack Overflow用户

发布于 2014-01-10 12:26:11

本例在标准中涵盖了:它是第8.5/17节第6项(强调我的):

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

  • 如果初始化是直接初始化,或者如果它是复制初始化,源类型的cv非限定版本是与目标类相同的类或派生类,则考虑构造函数。列举了适用的构造函数(13.3.1.3),并通过过载解析(13.3)选择了最优的构造函数。这样选择的构造函数被调用来初始化对象,初始化器表达式或表达式列表作为其参数。如果不应用构造函数,或者重载解析不明确,则初始化格式不正确.

Explanation:我们首先注意到,S是一个集合(第8.5.1/1节)。但是聚合也是,因此具有隐式声明的默认复制/移动构造函数(见第12.8节)。这两个构造函数都有一个论点,因此是可行的(由第13.3.2节)。他们的签名与往常一样:

代码语言:javascript
复制
S(const S&) //copy
S(S&&)      //move

现在,我们必须确定转换序列,以将初始化程序列表{1,2}转换为参数类型。§13.3.3.1.5/6指出:

否则,如果参数是引用,请参见13.3.3.1.4。注意:本节中的规则将适用于为引用初始化基础临时文件。-end注记

由于参数类型是引用的,因此适用第13.3.3.1.4/2号编:

当引用类型的参数没有直接绑定到参数表达式时,转换序列是根据13.3.3.1将参数表达式转换为引用的底层类型所必需的序列。概念上,此转换序列对应于使用参数表达式对基础类型的临时进行复制初始化。顶级cv限定中的任何差异都包含在初始化本身中,并不构成转换。

由于S是一个聚合,所以我们必须应用§13.3.3.1.5/5来初始化这个临时对象:

否则,如果参数具有可以根据聚合初始化规则(8.5.1)从初始化程序列表中初始化的聚合类型,则隐式转换序列是用户定义的转换序列,第二标准转换序列是标识转换。

因此,我们最终到达了这个临时对象的聚合初始化。要确定这两个构造函数中哪一个是最好的可行函数,必须查阅第13.3.3.2节(留给读者使用)。由于引用绑定到临时对象,因此将实际选择移动构造函数。

票数 4
EN

Stack Overflow用户

发布于 2014-01-10 01:55:58

声明S s({1, 2});S s({1});根据N3797§8.5 p16执行直接初始化。

好吧,是和不是。在第一种情况下,与第二种情况类似,S x-value对象是用{1, 2}构造的,然后传递给s l-值的隐式声明的复制构造函数。

这不是§8.5 p16正在讨论的情况,因为初始化不是以以下形式进行的:

代码语言:javascript
复制
S s(a);
S s{a};

除非标准认为a是任何东西。即使如此,它也不是他在后面定义的其他案例的一部分(newstatic_cast等)。

主题声明、S s({1, 2});S s({1});不是列表初始化,因为每个初始化器都是括号大小的大括号-init-列表。

表达式{1, 2}{1}绝对是临时/到期S对象的列表初始化。

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

https://stackoverflow.com/questions/20973417

复制
相关文章

相似问题

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