簡體   English   中英

為什么const / nonconst左值引用都綁定到右值引用?

[英]Why both const/nonconst lvalue references bind to a rvalue reference?

允許這個非常簡單的代碼:

class s
{
public:
};

const s& tt = std::move(s()); // Also valid without 'const'

但是現在我想知道它為什么被允許..

首先我們使用std::move並將rvalue(臨時)標記為rvalue引用,但為什么左值引用可以綁定到右值引用?

是因為右值參考也是右值?

導致左值引用綁定到右值引用的基本原理(或標准引號)是什么? 它可以做到我得到它。

編輯:msvc2015允許非對象左值引用綁定到右值引用,問題仍然是const值左側引用綁定到右值引用。 對不起,我應該指定我使用的編譯器。

Rvalue引用被隱式轉換為rvalues(更具體地說,轉換為xvalues)作為標准轉換之一(C ++標准的第4章):

任何隱式轉換的效果與執行相應的聲明和初始化相同,然后使用臨時變量作為轉換的結果。 如果T是左值引用類型或函數類型的右值引用(8.3.2),則結果是左值;如果T是對象類型的右值引用,則為xvalue ,否則為prvalue

Rvalues(包括xvalues)可以綁定到const左值引用,以便您可以使用這樣的參數將臨時值傳遞給函數:

void foo(const bar &a);
// ...
foo(bar());

(臨時是rvalue;在這種情況下, bar()的結果是rvalue)。 沒有理由不讓這一點,因為臨時,只要生活總是作為含有表達-在這種情況下,函數調用-所以它不會產生內部懸空參考foo

這意味着總是可以將函數fun(bar)的簽名調整為fun(const bar &) - 當然也可以相應地更改實現! - 因為臨時參數仍然被接受,並且從調用者的角度來看語義應該是相同的; const意味着不會修改對象,如果它是通過副本傳遞的話也是如此。

不允許非const引用; 一個實際的原因是因為它們暗示應該以某種有意義的方式修改價值,如果價值是暫時的,那么這將失去。 但是,如果您真的想這樣做,可以將右值轉換為左值,並提供一些警告,如另一個問題的答案中所述。

除了允許通過引用傳遞臨時參數之外,允許rvalue綁定到const左值引用也適用於未知確切參數類型但是如果可能允許移動語義的情況。 假設我正在調用一個可以定義為foo2(const bar &)foo2(bar)的函數,並且在前一種情況下可能有或沒有過載foo2(bar &&) ,我想允許移動語義到盡可能使用(假設foo2(bar &&)重載將在其實現中使用移動語義); 我可以安全地使用std::move創建一個rvalue,因為它適用於任何一種情況。 這個例子可能看起來有點人為,但在編寫模板時可能會出現相當多的問題。 在代碼中:

bar bb = bar();
foo2(std::move(bb));
// above is legal if foo2 is declared as either:
//    foo2(bar)
//    foo2(const bar &)
// and in latter case calls overload foo2(bar &&) if it is defined.

在涉及臨時的其他rvalue-to -valval-reference賦值的情況下,臨時的生命周期被擴展為引用的生命周期,因此即使在參數傳遞之外的上下文中也不會創建懸空引用:

const bar &b = bar(); // temporary lifetime is extended

在上面,在參考b超出范圍之前, bar對象不會被銷毀。

暫無
暫無

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

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