什么時候返回語句需要顯式移動?

[英]When is explicit move needed for a return statement?


In a comment to another question Jonathan Wakely responds to my statement:

在對另一個問題的評論中,Jonathan Wakely回應了我的陳述:

You never need explicit move for a local variable function return value. It's implicit move there

您永遠不需要顯式移動局部變量函數返回值。這是隱含的舉動

->

... never say never ... You need an explicit move if the local variable is not the same type as the return type, e.g. std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; }, but if the types are the same it will move if possible ...

...永遠不要說永遠......如果局部變量與返回類型的類型不同,則需要顯式移動,例如std :: unique_ptr f(){auto p = std :: make_unique (); P-> FOO();返回p; },但如果類型相同,它將盡可能移動...

So it seems sometimes we may have to move a local variable on return.

所以有時我們可能不得不在返回時移動局部變量。

The example

std::unique_ptr<base> f() { 
  auto p = std::make_unique<derived>();
  p->foo(); 
  return p; 
}

is nice in that it gives a compilation error

很好,因為它給出了編譯錯誤

> prog.cpp:10:14: error: cannot convert ‘p’ from type
> ‘std::unique_ptr<derived>’ to type ‘std::unique_ptr<derived>&&’

but I'm wondering whether there is a good chance to detect this in general -- and is this here a limit of the language rules or of unique_ptr??

但我想知道是否有一個很好的機會來檢測這一般 - 這是語言規則或unique_ptr的限制嗎?

1 个解决方案

#1


18  

Update:

Explicit move should not be needed in modern compiler versions.

在現代編譯器版本中不應該需要顯式移動。

Core DR 1579 changed the rules so that the return value will be treated as an rvalue even when the types are not the same. GCC 5 implements the new rule, for C++11 as well as C++14.

核心DR 1579更改了規則,以便即使類型不同,返回值也將被視為右值。 GCC 5為C ++ 11和C ++ 14實現了新規則。

Original answer:

This is not a limitation of unique_ptr, it's a limitation of the language, the same limitation applies to any return statement that calls a converting constructor taking an rvalue reference:

這不是unique_ptr的限制,它是語言的限制,同樣的限制適用於調用轉換構造函數采用右值引用的任何return語句:

struct U { };

struct T {
  T(U&&) { }
};

T f() {
  U u;
  return u;  // error, cannot bind lvalue to U&&
}

This will not compile because [class.copy]/32 says:

這不會編譯,因為[class.copy] / 32說:

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

當滿足或將滿足復制操作的省略標准時,除了源對象是函數參數這一事實,並且要復制的對象由左值指定,重載決策選擇復制的構造函數是首先執行,好像對象是由右值指定的。

This means that the expression in a return statement can only be treated as an rvalue if it is eligible for copy/move elision (aka NRVO) but that is too restrictive because it means it only applies when the type is exactly the same, even though the variable is always going out of scope so it would be reasonable to always treat is as an rvalue (technically as an xvalue, an expiring value.)

這意味着如果返回語句中的表達式符合復制/移動省略(也稱為NRVO)的條件,則只能將其視為右值,但這種限制性太強,因為這意味着它僅適用於類型完全相同的情況,即使變量總是超出范圍,所以總是把它作為一個rvalue(在技術上作為xvalue,一個到期值)是合理的。

This was recently suggested by Richard Smith (and previously by Xeo) and I think it's a very good idea.

最近由Richard Smith(以及之前的Xeo)提出過,我認為這是一個非常好的主意。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/07/05/72075ba3aee69592c7ffd8a5b74974c0.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com