下面的初始化是如何良构的?

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)