提问人:mada 提问时间:10/11/2023 更新时间:10/12/2023 访问量:178
prvalue 表达式的“结果对象”实际上是什么?
What actually a "result object" of a prvalue expression is?
问:
该标准在 [basic.lval]/5 中规定如下:
[..]prvalue 的结果对象是由 prvalue [..]
它与 [basic.lval]/(1.2) 中所述的 prvalue 定义同步:
prvalue 是一个表达式,其计算结果初始化对象 [..]
所以据我了解,对 prvalue 表达式的计算初始化了一个名为“结果对象”的对象,而这个“结果对象”就是由这个 prvalue 初始化的对象。例如:
struct S {};
int main(void){
S s = S();
}
这是一个 prvalue 表达式,我认为这是它的结果对象(可能不正确,这就是我所要求的),因为根据第一个引号,是由 prvalue 初始化的对象。现在,如果实际上是结果对象,那么结果对象在哪里:S()
s
s
S()
s
struct X {};
int main(void){
X();
}
这里 PRvalue 没有 result 对象,因为它没有被任何对象初始化;右?X()
当我在 Clang AST 中看到以下代码时,我陷入了这种困惑: (很抱歉试图打开一个不相关的问题,但我会总结 AFAIC)
struct Y {};
int main() {
Y y = Y();
}
以下是从上述代码生成的 AST:(...省略...
....
...
`-FunctionDecl <line:5:1, line:7:1> line:5:5 main 'int ()'
`-CompoundStmt <col:12, line:7:1>
`-DeclStmt <line:6:5, col:14>
`-VarDecl <col:5, col:13> col:7 y 'Y':'Y' cinit
`-CXXTemporaryObjectExpr <col:11, col:13> 'Y':'Y' 'void () noexcept' zeroing
最后一行清楚地表明创建了一个未实现的临时 get。当我试图理解为什么正确或错误地创建这个临时对象时,我在标准中检查了以下文本:([class.temporary]/3)
当类类型 X 的对象传递给函数或从函数返回时,如果 X 至少有一个合格的复制或移动构造函数 ([special]),则每个此类构造函数都是微不足道的,并且 X 的析构函数是微不足道的或已删除的,则允许实现创建一个临时对象来保存函数参数或结果对象。
[..]
我不确定我是否发现了正确的段落。但是如果是这样,上面的段落说创建的临时对象包含“结果对象”,我看到这里的结果对象是;右?我在这里感到困惑:结果对象如何同时尚未初始化?这里的结果对象是否是从构造函数调用生成的对象?还是别的什么?y
y
y
如果我的问题有任何冲突,或者这些问题是基于误解,我深表歉意。
答:
and I think that s is its result object
Yes, correct. In particular there is no temporary object that could be the result object instead (since C++17).
here X() prvalue has no result object because it isn't initialized by any objects; Right?
The expression in the expression statement is a discarded-value expression per [stmt.expr]/1.X()
X();
After potential conversions which are not relevant here, a prvalue expression that is a discarded-value expression has the temporary materialization conversion applied per [expr.context]/2.
The effect of temporary materialization conversion is to introduce a temporary object that is initialized from the prvalue per [conv.rval].
This temporary object is therefore the result object of the prvalue.
I fell into this confusion when I saw the following code in Clang AST
CXXTemporaryObjectExpr
probably (I am guessing here) only indicates an expression of the form where is a non-reference type and is either an empty expression list or a list of two or more expressions and isn't intended to state anything about applied temporary materialization conversions.T(E)
T
E
Before C++17, this syntax generally caused the creation of a temporary object (before optional copy elision), which is why the name makes sense. Since C++17 there are many cases where this expression syntax will not cause the creation of a temporary object as you demonstrate. They probably simply didn't change the Clang-internal naming.
Your quote from the standard is not relevant here since there is no function that takes or returns a .S
Note that the above applies to C++17 and later only.
评论
Y y = Y()
评论
X()
实际上确实创建了一个对象——一个临时的对象,在创建后立即再次销毁。您会注意到,如果您实现了一个自定义类,该类在构造函数和析构函数中提供了一些输出。这个对象,虽然没有赋值到任何地方,但它是结果对象......X()
Y
Y y; y = Y();
y
Y y = Y();
y
y
Y()
Y y = Y();
X();