8

Is, returning an lvalue reference to *this, allowed when *this is an rvalue?

#include <iostream>
#include <string>
using namespace std;

class A {
public:
    A& f() {
        return *this;
    }
    string val() const {
        return "works";
    }
};

int main() {
    cout << A{}.f().val();
}

Is there ANY scenario where the value returned by f() will be a dangling reference at some point?

Does calling f() prolongs the lifetime of the caller if this is an rvalue like in example?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
barsdeveloper
  • 930
  • 8
  • 28
  • I think your code is getting "lucky". If `val` referenced any member of `A`, then you would see the dangling reference clearly. – NG. Jul 08 '15 at 22:37
  • 2
    Your terminology needs improvement. lvalues and rvalues are *expression categories*, not flavours of object. The expression `*this` is an lvalue; `A{}` is an rvalue (prvalue) even though they designate the same temporary object. – M.M Jul 08 '15 at 22:46
  • 1
    You might consider `A& f() & {` to ensure the call is happening on an lvalue object if you need to do something like this. – chris Jul 08 '15 at 22:55

2 Answers2

10

*this is never an rvalue but in this case, it is (a reference to) a temporary. Temporaries are valid objects until the statement where they are defined is completed, i.e. until the code reaches the terminating ;, or until the end of the controlling expression for for, if, while, do, and switch statements, e.g. in if (A{}.f()) { something; }, the temporary is valid until the last ) before the body of the condition ({ something; }).

StenSoft
  • 9,369
  • 25
  • 30
  • Then it will be dangling reference if I use it in another instruction? – barsdeveloper Jul 08 '15 at 22:23
  • 3
    @biowep Yes, it will be a dangling reference in subsequent statements – StenSoft Jul 08 '15 at 22:24
  • 1
    @biowep For an example, add a destructor that prints something, and then write `A& a = A{}.f(); cout << a.val();`. Does the text from the destructor get printed before or after the value returned by `val()`? –  Jul 08 '15 at 22:25
  • 1
    More precisely: "Until the end of the full expression". E.g. http://coliru.stacked-crooked.com/a/d5554f6a7d041525 (Note that `i` is dead before we reach the next `;`.) – Baum mit Augen Jul 08 '15 at 22:50
  • 1
    @BaummitAugen `i` is not a temporary but a variable with scope of the `for` loop. Temporaries don't have names. But I have added the situation in controlling expressions for loops. – StenSoft Jul 08 '15 at 23:59
  • @StenSoft True, the example is wrong. Sorry, thanks for pointing this out. The formulation "Until the end of the full expression" is still correct. – Baum mit Augen Jul 09 '15 at 06:58
  • @BaummitAugen Temporaries created in controlling expression of an `if` are not valid in the body of the `if` statement while the `i` variable in your example is. – StenSoft Jul 09 '15 at 11:45
  • @StenSoft Yes, I know. I screwed up yesterday, what I wrote is wrong, the example did not fit the (correct) statement. The `3` lives until the end of the full expression, which in this case is the `)` of the `if` and `i` itself is of course not a temporary, as you already correctly pointed out.. – Baum mit Augen Jul 09 '15 at 11:49
-2

*this is not an rvalue. It is an lvalue.

So, no problem.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • @hvd: The question is _"Is, returning an lvalue reference to *this, allowed when *this is an rvalue?"_ The premise is broken, since `*this` is never an rvalue, and pointing that out is the only valid answer. – Lightness Races in Orbit Jul 08 '15 at 23:10
  • 2
    That's poor wording on the part of the OP, but pointing that out should be a comment, not an answer, when it's clear that that's not what the OP actually meant to ask. If you say it's not clear to you, then that's fine, but I'm pretty sure the OP is asking about calling member functions on rvalues, not actually about `*this` being an rvalue. –  Jul 09 '15 at 11:15
  • 1
    @hvd: It's not "poor wording". It's a broken premise, almost certainly stemming from a broken understanding. It's obviously not just a typo. If the OP would like to post another, different question then he or she is free to do so. But I have correctly answered _this_ question. – Lightness Races in Orbit Jul 09 '15 at 11:16