Is the following code causing undefined behavior?
std::map<int, vector<int>> foo()
{
return ...
}
BOOST_FOREACH(const int& i, foo()[42])
{
std::cout << i << std::endl;
}
If undefined, What is the good way to fix it? What if I use c++11 range-for loop instead of BOOST_FOREACH?
This is, unfortunately, most probably undefined behavior.
The problem is that you have two levels here:
std::map<...>
is an r-value, its lifetime will be expanded until the end of the full-expressionstd::vector<int>&
is an l-value reference (into an object), its lifetime is that of the object.The problem arises because the code (roughly) expands to something like:
// from
for (<init>: <expr>) {
<body>
}
// to
auto&& __container = <expr>;
for (auto __it = begin(container), __e = end(container); __it != __e; ++__it)
{
<init> = *__it;
<body>
}
The issue here is in the initialization of __container
:
auto&& __container = foo()[42];
If it where just foo()
, this would work, because the lifetime of std::map<...>
would be extended to match that of __container
, however in this case we get:
// non-standard gcc extension, very handy to model temporaries:
std::vector<int>& __container = { std::map<...> m = foo(); m[42] };
And thus __container
ends up pointing into the nether.