Reputation: 1037
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
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