1
votes
#include <iostream>
int func0(){
  int a = 0;
  return a;
}
int&& func1(){
   int a = 0;
   return a;
}
int main(){
  int&& result0 = func0();
  int&& result1 = func1();
}

return statement rules are:

  1. A function returns to its caller by the return statement.
  2. [...] the return statement initializes the glvalue result or prvalue result object of the (explicit or implicit) function call by copy-initialization from the operand.

The rule about how to initialize the object of the function call is only #2.

We know the expression func0() is a prvalue. The reference result0 need to bind an object, so temporary materialization conversion shall covert the prvalue to an xvalue, So the temporary object as the prvalue result object is initialized from the operand of return, then the reference reusult0 bind to the temporary object.

But we know the result1 is a reference and the return type of func1 is also reference. For this case, [stmt.return] does not clearly cover this case, because result1 is a reference rather than object(neither glvalue reuslt object nor prvalue result object), so what the rules about this case? If I miss something, please correct me.

3
Why ask this seperately? You could have added this doubt to the previous question considering your questions to revolve around return statement rules.Anirban166
@Anirban166 disagree -- this site uses a "1 question per question" format . This question about returning by reference is substantially different to the other questionM.M
@Anirban166 I think they are different questions.So I open a new postxmh0511

3 Answers

3
votes

Your analysis of result0 is correct.

But there's no temporary materialization in the result1 case. The "glvalue result" is a reference initialized by copy-initialization from the operand a, and copy-initialization of a reference to the same type means that the reference binds directly (dcl.init.ref/5, via dcl.init/17.2). Then result1 binds to the glvalue result.

This creates a dangling reference; a return statement is explicitly excluded from the lifetime extension rules (class.temporary/6.2).

In the case int result2 = func1(); then the glvalue result (a reference) undergoes lvalue-to-rvalue conversion with result object result2 , this causes undefined behaviour since the glvalue result was dangling.

2
votes

We know the expression func0 is a prvalue

Incorrect. func0 (the function name expression) is an lvalue. You are thinking of func0() (the function call expression) which is indeed a prvalue. The rest of the paragraph is correct.

I don't really follow your second paragraph so let me phrase it:

func1() is an xlvalue and the reference result will bind to that xvalue.

Very important: because you are returning a reference to an automatic storage variable you are left with a dangling reference.

1
votes

For this case, [stmt.return] does not clearly cover this case, because result1 is a reference rather than object(neither glvalue reuslt object nor prvalue result object), ...

No, it covers. Note the rule says "glvalue result or prvalue result object", which is not "glvalue result object or prvalue result object". See [basic.lvalue]/5:

The result of a glvalue is the entity denoted by the expression. The result of a prvalue is the value that the expression stores into its context; a prvalue that has type cv void has no result. A prvalue whose result is the value V is sometimes said to have or name the value V. The result object of a prvalue is the object initialized by the prvalue; ...

So the reference entity of the result of func1() is initialized with a.