簡體   English   中英

Rvalue引用和auto &&局部變量

[英]Rvalue reference and auto&& local variables

將局部變量定義為右值引用或轉發(通用)引用有什么意義? 據我所知,任何具有名稱的變量都是左值,並將被視為向前移動。

例:

Widget&& w1 = getWidget();
auto&& w2 = getWidget();

w1和w2都是左值,如果它們稍后作為參數傳遞,將被視為左值。 他們的decltype可能不是,但這有什么區別? 為什么有人需要這樣定義變量?

如果你有一個函數返回一個無法移動的臨時函數。

Foo some_function();

auto&& f = some_function();

這是合法的。 auto f = some_function(); 將復制(這可能是昂貴的),或無法編譯(如果該類也無法復制)。

通常, auto&&可以根據初始化的內容推斷為r或左值引用,如果使用臨時值初始化則延長其生命周期,同時允許您將其作為左值訪問。

經典用法是'just-loop'模式:

for( auto&& x : some_range )

實際上有一個auto&& x = *it; 在生成的代碼中。

您不能將非常量左值引用綁定到臨時值,因此您的另一個選擇是Widget const& ,它不允許您在其生命周期內修改臨時值。

此技術對於分解復雜表達式並查看正在發生的情況也很有用。 只要您不使用極其脆弱的表達式模板,就可以將表達式設為a+b+c*d並將其轉換為

auto&& c_times_d = d*d;
auto&& b_plus_c_times_d = b + decltype(c_times_d)c_times_d;
auto&& c_plus_b_plus_c_times_d = c + decltype(b_plus_c_times_d)b_plus_c_times_d;

現在您可以訪問其生命周期延長的臨時對象,並且您可以輕松地逐步執行代碼,或者在復雜表達式中的步驟之間引入額外的步驟:這是機械地發生的。

如果您未能綁定每個子表達式,則只關注脆弱的表達式模板。 (請注意,使用->可以生成大量您可能不會注意到的子表達式。)

當我想說“我正在存儲某些函數的返回值,而不是復制”時,我使用auto&& ,並且表達式的類型並不重要。 auto是我想制作本地副本的時候。

在通用代碼中,它非常有用。

Foo const& a(Foo*);
Bar a(Bar*);

template<class T>
auto do_stuff( T*ptr ) {
  auto&& x = a(ptr);
}

這里如果你傳遞一個Bar*它存儲臨時值,但是如果你將一個Foo*傳遞給do_stuff它會存儲const&

它盡力而為。

下面是一個返回不可移動的不可復制對象的函數示例,以及auto&&如何存儲它。 它沒用,但它顯示了它的工作原理:

struct Foo {
  Foo(&&)=delete;
  Foo(int x) { std::cout << "Foo " << x << " constructed\n";
};
Foo test() {
  return {3};
}

int main() {
  auto&& f = test();
}

據我所知,沒有真正的,也就是廣泛使用的目的來定義局部右值引用,因為它們的性質,不綁定到左值,只對重載和推導有幫助,所以將它們定義為函數的參數。

可以使用它們,將它們綁定到臨時值,如int &&rref = 5*2; 但由於幾乎所有的編譯器都在優化表達式int i = 5*2; 沒有實際需要,性能不佳或避免復制。

一個例子可以是一個數組

template<class T, int N> using raw_array = T[N];

然后

auto && nums = raw_array<int,4>{101, 102, 103, 104};

這允許臨時使用,就好像它是一個普通的數組。

聲明為auto&&的變量將遵循完美的轉發規則。 親自試試吧。 這甚至是在c ++ 14中使用lambdas完成轉發的完美方式。

const Type& fun1();
Type&& fun2();

auto&& t1 = fun1(); // works
auto&& t2 = fun2(); // works too

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM