我会回答你的问题...反过来。
为什么他们允许Foo const& foo = fooByValue(); 以 开头?
它使生活(在某种程度上)更轻松,但会在各处引入潜在的未定义行为。
Foo const& fooByReference()
{
return fooByValue(); // error: returning a reference to a temporary
}
这显然是错误的,编译器确实会尽职尽责地报告它。 根据 Tomalak 的评论:标准没有强制要求,但好的编译器应该报告它。 Clang、gcc 和 MSVC 都可以。我认为 Comeau 和 icc 也会。
Foo const& fooByIndirectReference()
{
Foo const& foo = fooByValue(); // OK, you're allowed to bind a temporary
return foo; // Generally accepted
}
这是错误的,但更微妙。问题是临时的生命周期绑定到foo 的生命周期,它在函数结束时超出了范围。 foo 的副本被传递给调用者,该副本指向以太。
我在 Clang 上提出了错误,Argyris 能够诊断出这种情况(真的很赞:p)。
Foo const& fooForwarder(Foo const&); // out of line implementation which forwards
// the argument
Foo const& fooByVeryIndirectReference()
{
return fooForwarder(fooByValue());
}
fooByValue 创建的临时对象绑定到fooForwarder 参数的生命周期,它尽职尽责地提供(引用的)副本,该副本返回给调用者,即使它现在指向以太.
这里的问题是fooForwarder 的实现完全符合标准,但它在其调用者中创建了未定义的行为。
但令人生畏的事实是,诊断此问题需要了解 fooForwarder 的实现,而这对于编译器来说是遥不可及的。
我能理解的唯一解决方案(除了 WPA)是运行时解决方案:每当一个临时对象绑定到一个引用时,您需要确保返回的引用不共享相同的地址......然后是什么? assert ?引发异常?而且由于它只是一个运行时解决方案,显然不能令人满意。
将临时绑定到引用的想法很脆弱。