下面的初始化是如何良构的?
How is the initialization below well-formed?
[class.conv.ctor]/2中的示例包含以下初始化:
Z a3 = Z(1); // OK: direct initialization syntax used
这如何被视为直接初始化语法?
Z(1)
将直接初始化纯右值。 prvalue 然后将用于初始化对象。到 为止,没有临时后跟副本。纯右值直接初始化对象。因此,Z a3 = Z(1);
完全等同于 Z a3(1);
。
在 C++17 之前的版本中,这将执行纯右值临时变量的直接初始化,然后将临时变量(几乎肯定被删除)复制到对象中 a3
。无论副本是否被省略,纯右值的初始化都是通过直接初始化。 a3
的初始化是复制初始化,但这是通过复制构造函数,而不是explicit
。
它正在谈论 Z(1)
。 [dcl.init]/16:
The initialization that occurs in [...] functional notation type
conversions (5.2.3) [...] is called direct-initialization.
纯右值然后用于复制初始化 z
,这很好,无论是否保证省略 - Z
的 copy/move 构造函数不是 explicit
无论如何,即使没有 C++17 中的保证省略,初始化也很好。
(警告:我对新概念还不是很熟悉,但下面的分析似乎是正确的)。首先,您需要从函数式转换表达式 Z(1);
开始。请注意,据说此 prvalue 表达式使用 直接初始化 来初始化一些 结果对象 。 这个对象是哪个,未指定,稍后决定,不是这个函数式表达式!
现在,关于纯右值的结果对象
The result object of a prvalue is the object initialized by the prvalue; ... [... For a discarded prvalue, a temporary object is materialized; see Clause [expr]. ... ]
我们先举个案例Z(1);
的例子,应该有助于理解这个概念。这是一个表达式语句,是一个丢弃值表达式。对于这样的表达式,规则说
... If the expression is a prvalue ..., the temporary materialization conversion ([conv.rval]) is applied.
并且每当应用此 "temporary materialization" 转换时,都会创建一个临时 对象 并根据该 prvalue 初始化 。
This conversion initializes a temporary object ([class.temporary]) of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object
哇,像 Z(1);
这样的简单语句需要所有这些。现在谈谈你的情况,Z a3 = Z(1);
。为此,结果对象更直接由8.6p17
指定
If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object.
Viola,我们有一个语义为 "direct-initialize a yet unknown object X by 1" 的表达式,然后另一个规则提供了这个对象 "X"。特别是每个 class-prvalue 表达式直接创建对象的 C++17 之前的模型已经过时了。这特别意味着不涉及复制构造函数或移动构造函数,但据我所知,您的代码 完全等同于 至 Z a3(1)
。
[class.conv.ctor]/2中的示例包含以下初始化:
Z a3 = Z(1); // OK: direct initialization syntax used
这如何被视为直接初始化语法?
Z(1)
将直接初始化纯右值。 prvalue 然后将用于初始化对象。到 Z a3 = Z(1);
完全等同于 Z a3(1);
。
在 C++17 之前的版本中,这将执行纯右值临时变量的直接初始化,然后将临时变量(几乎肯定被删除)复制到对象中 a3
。无论副本是否被省略,纯右值的初始化都是通过直接初始化。 a3
的初始化是复制初始化,但这是通过复制构造函数,而不是explicit
。
它正在谈论 Z(1)
。 [dcl.init]/16:
The initialization that occurs in [...] functional notation type conversions (5.2.3) [...] is called direct-initialization.
纯右值然后用于复制初始化 z
,这很好,无论是否保证省略 - Z
的 copy/move 构造函数不是 explicit
无论如何,即使没有 C++17 中的保证省略,初始化也很好。
(警告:我对新概念还不是很熟悉,但下面的分析似乎是正确的)。首先,您需要从函数式转换表达式 Z(1);
开始。请注意,据说此 prvalue 表达式使用 直接初始化 来初始化一些 结果对象 。 这个对象是哪个,未指定,稍后决定,不是这个函数式表达式!
现在,关于纯右值的结果对象
The result object of a prvalue is the object initialized by the prvalue; ... [... For a discarded prvalue, a temporary object is materialized; see Clause [expr]. ... ]
我们先举个案例Z(1);
的例子,应该有助于理解这个概念。这是一个表达式语句,是一个丢弃值表达式。对于这样的表达式,规则说
... If the expression is a prvalue ..., the temporary materialization conversion ([conv.rval]) is applied.
并且每当应用此 "temporary materialization" 转换时,都会创建一个临时 对象 并根据该 prvalue 初始化 。
This conversion initializes a temporary object ([class.temporary]) of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object
哇,像 Z(1);
这样的简单语句需要所有这些。现在谈谈你的情况,Z a3 = Z(1);
。为此,结果对象更直接由8.6p17
If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object.
Viola,我们有一个语义为 "direct-initialize a yet unknown object X by 1" 的表达式,然后另一个规则提供了这个对象 "X"。特别是每个 class-prvalue 表达式直接创建对象的 C++17 之前的模型已经过时了。这特别意味着不涉及复制构造函数或移动构造函数,但据我所知,您的代码 完全等同于 至 Z a3(1)
。