C++ 延长临时工的寿命

C++ 延长临时工的寿命,c++,reference,constants,temporary,rvalue,C++,Reference,Constants,Temporary,Rvalue,允许这样做的设计原理是什么 const Foo& a = function_returning_Foo_by_value(); 但不是这个 Foo& a = function_returning_Foo_by_value(); ? 第二行中可能出现的错误(第一行中不会出现错误)“可能出现的错误”是修改对象后立即丢失更改,因此定义了规则以帮助您避免犯此类错误。您可能会认为,如果再次调用该函数,您将得到一个包含更改的对象,当然不会,因为您修改了一个副本 典型的情况是,您创建一个临

允许这样做的设计原理是什么

const Foo& a = function_returning_Foo_by_value();
但不是这个

Foo& a = function_returning_Foo_by_value();
?

第二行中可能出现的错误(第一行中不会出现错误)

“可能出现的错误”是修改对象后立即丢失更改,因此定义了规则以帮助您避免犯此类错误。您可能会认为,如果再次调用该函数,您将得到一个包含更改的对象,当然不会,因为您修改了一个副本

典型的情况是,您创建一个临时方法,然后对其调用一个非常量方法,这是在您要交换它时:

std::string val;
some_func_that_returns_a_string().swap( val );

这有时非常有用。

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

原因有很多,我将只展示一个涉及隐式加宽转换的经典示例:

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

struct SpecialFoo : Foo {};
SpecialFoo* p;
if (CreateFoo(p)) { /* DUDE, WHERE'S MY OBJECT! */ }
允许常量引用绑定临时变量的基本原理是,它支持完全合理的代码,如下所示:

bool validate_the_cat(const string&);

string thing[3];
validate_the_cat(thing[1] + thing[2]);

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

我将回答您的问题。。。反过来说

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

它使生活变得(有些)简单,但却在各地引入了潜在的未定义行为

Foo const& fooByReference()
{
  return fooByValue(); // error: returning a reference to a temporary
}

这显然是错误的,事实上,编译器会尽职尽责地报告它。根据Tomalak的评论:标准没有强制要求它,但是好的编译器应该报告它。Clang、gcc和MSVC都有。我认为Comeau和icc也会

这是错误的,但更微妙。问题在于,临时变量的生存期与
foo
的生存期绑定,这超出了函数末尾的范围。将
foo
副本传递给调用者,该副本指向以太

我在Clang上提出了这个bug,Argyris能够诊断出这个病例(真的很荣幸:p)

fooByValue
创建的临时值绑定到
foofrowarder
参数的生存期,该参数尽职尽责地提供一个副本(引用的副本),该副本返回给调用方,即使它现在指向以太

这里的问题是
foodforwarder
的实现在标准中是完美的,但它在其调用者中创建了未定义的行为

然而,令人望而生畏的事实是,诊断这一问题需要了解
fooForwarder
的实现,这是编译器无法触及的

我能理解的唯一解决方案(除了WPA)是运行时解决方案:每当一个临时对象绑定到一个引用时,您需要确保返回的引用不共享相同的地址。。。然后呢<代码>断言
?提出一个例外?而且,由于这只是一个运行时解决方案,显然并不令人满意


将临时文件绑定到引用的想法很脆弱。

我理解的基本原理如下:临时文件超出范围时会被销毁如果您承诺不修改它,我会让您延长它的使用寿命。

为什么我会丢失更改?看看我问题的标题,临时变量将与
a
一样长,就像在
const Foo&
案例中一样。此代码显示的问题是右值不应绑定到正常引用。它没有说明为什么右值应该绑定到常量引用。爱这家伙,我的目标在哪里:)@David:
const-Foo*&
不是const-reference。你是说
Foo*const&
?我的错!我应该更加小心。。。我有直觉和测试,但我做了错误的测试。你是对的。我删除了我出丑的评论:)+1@JeskoHüttenhain它是指向指针的引用,而不是指向引用的指针。对指针的引用可能会被用于重置指针并用分配的对象替换它。哦,我明白了。我需要更好地阅读C++类型。嗯,那么,这实际上是一个很好的例子。这不是萨特在这里讨论的问题吗?”DunbCuffel:不,Habor萨特设计了使用WRT到C++标准,而弗莱德讨论了标准背后的原理。“这显然是错误的,而且如果你幸运的话,编译器会尽职地报告它”。如果你有一个工具链,如果你的警告被设置到某个级别,等等。C++语言不允许对这种情况进行诊断。@ Tomalak:我会纠正,至少MSVC,GCC和CLAN报告过,我认为科莫和ICC也会。
Foo const& fooByIndirectReference()
{
  Foo const& foo = fooByValue(); // OK, you're allowed to bind a temporary
  return foo;                    // Generally accepted
}
Foo const& fooForwarder(Foo const&); // out of line implementation which forwards
                                     // the argument

Foo const& fooByVeryIndirectReference()
{
  return fooForwarder(fooByValue());
}