延长临时工的寿命

fre*_*low 14 c++ const reference temporary rvalue

允许这样做的背后的设计理由是什么?

const Foo& a = function_returning_Foo_by_value();
Run Code Online (Sandbox Code Playgroud)

但不是这个

Foo& a = function_returning_Foo_by_value();
Run Code Online (Sandbox Code Playgroud)

第二行可能出现什么问题(第一行不会出错)?

Ben*_*igt 5

非常量指针不能延长临时变量的生命周期的原因是非常量引用首先不能绑定到临时变量。

造成这种情况的原因有很多,我将仅展示一个涉及隐式扩展转换的经典示例:

struct Foo {};
bool CreateFoo( Foo*& result ) { result = new Foo(); return true; }

struct SpecialFoo : Foo {};
SpecialFoo* p;
if (CreateFoo(p)) { /* DUDE, WHERE'S MY OBJECT! */ }
Run Code Online (Sandbox Code Playgroud)

允许 const 引用绑定临时对象的基本原理是,它可以实现完全合理的代码,如下所示:

bool validate_the_cat(const string&);

string thing[3];
validate_the_cat(thing[1] + thing[2]);
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下不需要延长寿命。


Mat*_* M. 5

我会回答你的问题……反过来。

为什么他们允许Foo const& foo = fooByValue();开始?

它使生活(在某种程度上)更轻松,但会在各处引入潜在的未定义行为。

Foo const& fooByReference()
{
  return fooByValue(); // error: returning a reference to a temporary
}
Run Code Online (Sandbox Code Playgroud)

这显然是错误的,编译器确实会尽职尽责地报告它。根据 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
}
Run Code Online (Sandbox Code Playgroud)

这是错误的,但更微妙。问题是临时对象的生命周期绑定到 的生命周期foo,它在函数结束时超出范围。甲拷贝foo被传递给调用者,并且该复制点入乙醚。

我在 Clang 上提出了错误,Argyris 能够诊断出这个案例(真的很赞:p)。

Foo const& fooForwarder(Foo const&); // out of line implementation which forwards
                                     // the argument

Foo const& fooByVeryIndirectReference()
{
  return fooForwarder(fooByValue());
}
Run Code Online (Sandbox Code Playgroud)

创建的临时fooByValue对象绑定到 的参数的生命周期fooForwarder,它尽职尽责地提供(引用的)副本,该副本返回给调用者,即使它现在指向以太。

这里的问题是 thatfooForwarder的实现完全符合标准,但它在调用者中创建了未定义的行为。

但令人生畏的事实是,诊断这一点需要了解 的实现fooForwarder,而这对于编译器来说是遥不可及的。

我能理解的唯一解决方案(除了 WPA)是运行时解决方案:每当临时对象绑定到引用时,您需要确保返回的引用不共享相同的地址......然后呢?assert? 引发异常?而且由于它只是一个运行时解决方案,它显然不能令人满意。

将临时对象绑定到引用的想法很脆弱。