1

I found the blow code compiles, even though get is called on a temporary, and the returned reference refers to a field of a temporary. Since it's not being used to initialize a const reference, the temporary should be destroyed once int& x = Test(5).get(); executes, correct? Therefore, does this leave x a dangling reference?

#include <iostream>

struct Test {
    int field;
    Test(int x) : field(x) {}
    
    int& get() {
        return field;
    }
};


int main()
{
    int& x = Test(5).get();
    std::cout << x;
}
confused
  • 11
  • 2
  • 4
    Correct. It's a dangling reference, and the code has **undefined behavior**. – Eljay Aug 22 '22 at 19:21
  • 1
    Yep, you're reading leftover data from a part of the stack that CAN get reused. The fact that it happens to work for you does not mean it will work on any other system, or even for you in the future.. That's the danger of undefined behavior. – Tim Roberts Aug 22 '22 at 19:22
  • 1
    That's right, big problem. You might want to declare `get` like this: `int& get() & { return field; }` and then it can only be called on lvalues, and will help prevent such mistakes at compile time. (But with field being a public data member, it doesn't offer much protection. =) – Chris Uzdavinis Aug 22 '22 at 19:25
  • @ChrisUzdavinis is that a newer standard language feature? – πάντα ῥεῖ Aug 22 '22 at 19:26
  • 2
    @πάνταῥεῖ member function refererence qualification was introduced in C++11: https://stackoverflow.com/questions/47002799/what-does-the-ampersand-at-the-end-of-member-function-signature-mean – NathanOliver Aug 22 '22 at 19:30
  • 2
    @NathanOliver: That said [almost nothing in the standard library uses it](https://stackoverflow.com/q/54116810/364696), so it's not unusual for people to overlook it. – ShadowRanger Aug 22 '22 at 19:31
  • @ShadowRanger I would assume the "lets not break old code" mindset was part of that. There are also times where a temporary is what you want. I would hate if my favorite one liner for finding if there are duplicates in a container stopped working. – NathanOliver Aug 22 '22 at 19:34
  • If the lvalue overload of `get` returns a reference, we could make an rvalue overload return by-value to be safe, and still work as a one-liner. – Chris Uzdavinis Aug 22 '22 at 19:44
  • @nathan thanks for the info, in fact I've been doing relatively few coding under c++11 standards. And yes, it's an easy to overlook feature, since it's a rare edge case to consider. A `const` reference always guaranteed prolongation of lifetime. Would be nice to have another duplicate for that specific feature as well, and I believe this q is a good signpost (upvoting). – πάντα ῥεῖ Aug 22 '22 at 20:17

0 Answers0