以下代码是否导致未定义的行为?
std::map<int, vector<int>> foo()
{
return ...
}
BOOST_FOREACH(const int& i, foo()[42])
{
std::cout << i << std::endl;
}
如果未定义,修复它的好方法是什么?如果我使用c 11 range-for循环而不是BOOST_FOREACH怎么办?
解决方法:
不幸的是,这很可能是未定义的行为.
问题是你有两个级别:
> std :: map< ...>是一个r值,它的生命周期将扩展到完整表达式的结束
> std :: vector< int>&是一个l值引用(进入一个对象),它的生命周期是对象的生命周期.
问题出现是因为代码(粗略地)扩展到类似的东西:
// from
for (<init>: <expr>) {
<body>
}
// to
auto&& __container = <expr>;
for (auto __it = begin(container), __e = end(container); __it != __e; ++__it)
{
<init> = *__it;
<body>
}
这里的问题是__container的初始化:
auto&& __container = foo()[42];
如果它只是foo(),这将起作用,因为std :: map< ...>的生命周期将被扩展为与__container的匹配,但在这种情况下,我们得到:
// non-standard gcc extension, very handy to model temporaries:
std::vector<int>& __container = { std::map<...> m = foo(); m[42] };
因此__container最终指向幽冥.