Picard
Picard

Reputation: 1037

Returning a reference to a temporary

I'm watching this talk from cppcon17 and am trying to replicate and understand the presented bugs. However, I'm not able to replicate/understand bug #3 in the talk (timestamp is in the link above). I've written this minimal example:

#include <iostream>
#include <map>


const std::string& getDefault(const std::map<int, std::string>& map, const int key, const std::string& defVal) {
    auto pos = map.find(key);
    return (pos != map.end() ? pos->second : defVal);
}

void printer(const std::string& str) {
    std::cout << str << std::endl;
}

int main () {
    std::map<int, std::string> myMap { {1, "dog"}, {2, "cat"}};
    auto& retVal = getDefault(myMap, 3, "pizza");
    printer(retVal);
    return 0;
}

As I understand the problem, the temporary default value of "pizza" should not be returned by reference, because it should get deleted. But why does this example work anyway? I was expecting an error due to a reference that is no longer valid.

Edit: I've modified the example slightly to highlight that the problem still occurs, if the temporary is on another line.

Upvotes: 2

Views: 66

Answers (1)

songyuanyao
songyuanyao

Reputation: 172894

This code, i.e. std::cout << getDefault(myMap, 3, "pizza") << std::endl; is valid; the temporary will be destroyed after the full expression, i.e. after the ;, the returned reference remains valid when being passed to and printed out by operator<< of std::cout.

All temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created,

EDIT

Your updated code has undefined behavior. After the ; the temporary object has been destroyed and retVal is dangled; any dereference on it leads to UB.

Upvotes: 4

Related Questions