5

Consider the following C++ code.

struct foo { std::string value; }

inline foo bar() { return { "42" }; }

Now imagine I have a function that uses bar() in the following way.

std::string my_func()
{
    const auto &x = bar();
    return x.value;
}

Does this leak memory Because my_func only holds a reference to x? Or does x still get cleaned up after my_func terminates?

I know this is not how references are supposed to be used. But I just realized this compiles fine and wondered what the semantics of it are.

Kai Mast
  • 213
  • 2
  • 7

4 Answers4

7

But I just realized this compiles fine

Code provided should not compile, as trying to assign temporary to lvalue reference.

error: invalid initialization of non-const reference of type ‘foo&’ from an rvalue of type ‘foo’

If you fix code, by

std::string my_func()
{
    const auto &x = bar();
    return x.value;
}

then it would be fine, as const reference extends lifetime of temporary for lifetime of const reference.

Slava
  • 43,454
  • 1
  • 47
  • 90
4

Short answer: no.

Longer answer: In that case, the compiler will make sure, that the referenced temporary object will live to the end of the current scope. bar() returns n object by value. That will be copied into a temporary, anonymous object and the reference will then reference that temporary object.

There are other situations similar to that, where the standard has this explicit requirement: temporaries that are bound to references live until the end of the current scope is reached.

cdonat
  • 2,748
  • 16
  • 24
1

No, the string is copied into the return value. Object referenced by x goes out of scope after the function.

pewpew
  • 39
  • 1
1

This is not a leak, your reference just points to memory that was cleaned up by stack unwinding, due to a temp. object.

Accessing x will result in an undefined behaviour. Probably an access violation.

Viktor Liehr
  • 508
  • 4
  • 14
  • I have been using a very similar line of code in my project for about a month without any issues. That is what was confusing to me. – Kai Mast Nov 05 '15 at 21:34
  • @KaiMast: Hard to say why it is working for you without knowing what you mean with similar. For example, when you return a reference to an static variable, that will work for you. If you want to share us your code snippet, maybe we can say more why it is working for you. – Viktor Liehr Nov 05 '15 at 21:38
  • The reference doesn't point to memory that was cleaned up, anywhere in this code. – nos Nov 05 '15 at 21:38
  • @ViktorLiehr original code should not compile, for fixed code your answer is incorrect. – Slava Nov 05 '15 at 21:39
  • @nos: What do you think what happened here and what a reference really is? – Viktor Liehr Nov 05 '15 at 21:40
  • @VicroeLiehr bar() returns a foo object. The `x ` reference is bound to the temporary object returned from bar(), which is perfectly fine since the reference is const. `x.value` is then copied into the return value of `my_func`, at the end of `my_func` the temp object bound to `x` is destroyed. Nothing is leaked, nothing is pointing to memory you can't access. – nos Nov 05 '15 at 21:42
  • @nos: Precisely, it is const, so it mean it is a const reference which cant reference to another object. But still it refereces to an temp. object that is going to be destroid. After that, this point of memory is garbage. – Viktor Liehr Nov 05 '15 at 21:48
  • @ViktorLiehr The temp object is destroyed at the end of the scope of the const reference bound to it, the `x`. Here its scope the end of the my_func() function. Which line of code are you implying would access anything in this temp object after it is destroyed ? Note that the return value of my_func() is a std::string, not a reference, nor a pointer. x.value is copied to the return value of `my_func`, that happens before the temp object is destroyed. – nos Nov 05 '15 at 21:53
  • @nos: Your comment does't make sense at all. Please read the question again + source code and my anwer so this again. – Viktor Liehr Nov 05 '15 at 21:55
  • @ViktorLiehr I have read the source code. I have read your answer. Your answer does not match other answers here either. Please make sure you are looking at the updated code of the poster, the original code would not compile. I'm also assuming that you know how const references to a temp object behaves. That is why I wonder which line of code you claim accesses `x` that would result in undefined behavior. – nos Nov 05 '15 at 21:58
  • @nos: The addition was the const reference, so why do you think it changes something? Look again, it is referecing to an temp. memory that is going to be released very soon. So, please, explain it to us all what makes you wonder. – Viktor Liehr Nov 05 '15 at 22:02
  • @ViktorLiehr Sorry, no that is not how const references to a temporary object work. const really do change things. It appears that you are not going to take my word for it, so you should probably read [this](http://stackoverflow.com/questions/11560339/returning-temporary-object-and-binding-to-const-reference) , [this](http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary) , [this](http://en.cppreference.com/w/cpp/language/lifetime) Or section §12.2/5 in the C++ standard – nos Nov 05 '15 at 22:08
  • @nos: I read the articles you referenced. Thx, buddy! Just learned that a const reference behaves different. That makes a very big change! – Viktor Liehr Nov 05 '15 at 22:20