延长临时的寿命 [英] prolonging the lifetime of temporaries

查看:146
本文介绍了延长临时的寿命的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

允许此操作的设计原理是什么

  const Foo& a = function_returning_Foo_by_value(); 

但不是

  Foo& a = function_returning_Foo_by_value(); 



在第二行(第一行不会出错)?

解决方案

我会回答你的问题。



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



它使生活更容易,但引入了潜在的未定义的行为。

  Foo const& fooByReference()
{
return fooByValue(); //错误:返回对临时的引用
}

这显然是错误的,确实编译器会尽职报告。 根据Tomalak的意见:它不是标准的强制,但良好的编译器应该报告它。 Clang,gcc和MSVC做。我认为Comeau和icc也太。



  Foo const& fooByIndi​​rectReference()
{
Foo const& foo = fooByValue(); // OK,你可以绑定一个临时
return foo; //一般接受
}

这是错误的,但更微妙。问题是临时的生命周期是绑定到生命周期 foo ,超出范围在函数的结尾。 foo 副本传递给调用者,此副本指向以太网。



我提出了Clang的错误,而Argyris能够诊断这种情况(真正的是:p)。

  Foo常数& fooForwarder(Foo const&); // out of line implementation which forward 
//参数

Foo const& fooByVeryIndi​​rectReference()
{
return fooForwarder(fooByValue());
}

fooByValue创建的临时绑定到 fooForwarder 的参数的生命周期,它尽可能提供一个副本(引用),副本返回给调用者,即使它现在点进入醚。



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



令人生畏的事实是,诊断这需要了解 fooForwarder

唯一的解决方案,我可以fathom(除了WPA)是一个运行时解决方案:每当一个临时被绑定到一个引用,那么你需要确保返回的引用不共享相同的地址...然后什么? assert ?引发异常?



将临时数据绑定到引用的想法很脆弱。 p>

What is the design rationale behind allowing this

const Foo& a = function_returning_Foo_by_value();

but not this

Foo& a = function_returning_Foo_by_value();

?

What could possible go wrong in the second line (which would not already go wrong in the first line)?

解决方案

I'll answer your question... the other way around.

Why did they allowed Foo const& foo = fooByValue(); to begin with ?

It makes life (somewhat) easier, but introduces potential undefined behavior all over the place.

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

This is obviously wrong, and indeed the compiler will dutifully report it. As per Tomalak's comment: it is not mandated by the standard, but good compilers should report it. Clang, gcc and MSVC do. I think that Comeau and icc would too.

Foo const& fooByIndirectReference()
{
  Foo const& foo = fooByValue(); // OK, you're allowed to bind a temporary
  return foo;                    // Generally accepted
}

This is wrong, but is more subtle. The problem is that the lifetime of the temporary is bound to the lifetime of foo, which goes out of scope at the end of the function. A copy of foo is passed to the caller, and this copy points into the ether.

I raised the bug on Clang, and Argyris was able to diagnose this case (kudos really :p).

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

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

The temporary created by fooByValue is bound to the lifetime of the argument of fooForwarder, which dutifully provide a copy (of the reference), copy that is returned to the caller, even though it now points into the ether.

The issue here is that fooForwarder's implementation is perfectly fine wrt the standard, and yet it creates undefined behavior in its caller.

The daunting fact though, is that diagnosing this requires knowing about the implementation of fooForwarder, which is out of reach for the compiler.

The only solution I can fathom (apart from WPA) is a runtime solution: whenever a temporary is bounded to a reference, then you need to make sure that the returned reference does not share the same address... and then what ? assert ? raise an exception ? And since it's only a runtime solution, it is clearly not satisfactory.

The idea of binding a temporary to a reference is brittle.

这篇关于延长临时的寿命的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆