The standard states in [basic.lval]/5 the following:
[..] The result object of a prvalue is the object initialized by the prvalue [..]
which is synchronized with the definition of a prvalue stated in [basic.lval]/(1.2):
A prvalue is an expression whose evaluation initializes an object [..]
So as far as I understand, the evaluation of a prvalue expression initializes an object called "result object", and this "result object" is the object that's initialized by this prvalue. For example:
struct S {};
int main(void){
S s = S();
}
here S() is a prvalue expression, and I think that s is its result object (may be incorrect, and that's what I am asking for) because, per the first quote, s is the object initialized by the prvalue S(). Now, if s actually is the result object, where does the result object here:
struct X {};
int main(void){
X();
}
here X() prvalue has no result object because it isn't initialized by any objects; Right?
I fell into this confusion when I saw the following code in Clang AST: (I'm sorry for trying to open an unrelated question, but I will summarize AFAIC)
struct Y {};
int main() {
Y y = Y();
}
The following is the AST produced from the above code: (...omitted...)
....
...
`-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
The last line shows clearly there's an un-materialized temporary get created. When I tried to understand why this temporary object was created, correctly or incorrectly, I checked this text in the standard: ([class.temporary]/3)
When an object of class type X is passed to or returned from a function, if X has at least one eligible copy or move constructor ([special]), each such constructor is trivial, and the destructor of X is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object.
[..]
I'm not sure that I have spotted the correct paragraph. But if so, the above paragraph says that the created temporary object holds the "result object", and I see that the result object here is y; right? I have confusion here: how the result object is y meanwhile y is not yet initialized? Does the result object here is the object produced from the constructor call? or something else?
I apologize if there are any conflicts in my questions or if the questions are based on misunderstanding.
Yes, correct. In particular there is no temporary object that could be the result object instead (since C++17).
The expression
X()in the expression statementX();is a discarded-value expression per [stmt.expr]/1.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.
CXXTemporaryObjectExprprobably (I am guessing here) only indicates an expression of the formT(E)whereTis a non-reference type andEis 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.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.