a 的范围初始化行for(:)
循环不会延长任何东西的生命周期,除了final临时的(如果有的话)。任何其他临时文件在执行之前都会被丢弃for(:)
循环执行。
现在,不要绝望;这个问题有一个简单的解决方法。但首先要了解一下出了什么问题。
代码for(auto x:exp){ /* code */ }
基本上扩展到:
{
auto&& __range=exp;
auto __it=std::begin(__range);
auto __end=std::end(__range);
for(; __it!=__end;++__it){
auto x=*__it;
/* code */
}
}
(带着谦虚的谎言__it
and __end
行,以及所有以__
没有可见的名字。我还展示了 C++17 版本,因为我相信有一个更美好的世界,这里的差异并不重要。)
Your exp
创建一个临时对象,然后返回对其内部的引用。临时对象在该行之后消失,因此代码的其余部分有一个悬空引用。
修复它相对容易。要解决这个问题:
std::string const& func() const& // notice &
{
return m.find("key")->second;
}
std::string func() && // notice &&
{
return std::move(m.find("key")->second);
}
执行右值重载并返回移入的值by value当使用临时对象而不是返回对它们的引用时。
Then the
auto&& __range=exp;
行对返回的按值引用生命周期扩展string
,并且不再有悬空的引用。
作为一般规则,永远不要通过引用可能是右值的参数来返回范围。
附录:等等,&&
and const&
方法之后?右值引用*this https://stackoverflow.com/q/8610571/1774667?
C++11 添加了右值引用。但是this
或者函数的 self 参数是特殊的。要根据被调用对象的右值/左值性质选择方法的重载,您可以使用&
or &&
方法结束后。
这与函数参数的类型非常相似。&&
在该方法声明该方法只能在非常量右值上调用之后;const&
意味着应该为常量左值调用它。不完全匹配的事物遵循通常的优先规则。
当您有一个返回对象引用的方法时,请确保使用&&
重载并且在这些情况下不返回引用(返回值),或者=delete
方法。