簡體   English   中英

右值引用被視為左值?

[英]Rvalue Reference is Treated as an Lvalue?

我發布了這個答案: https://stackoverflow.com/a/28459180/2642059其中包含以下代碼:

void foo(string&& bar){
    string* temp = &bar;

    cout << *temp << " @:" << temp << endl;
}

bar是右值還是左值?

我問是因為我顯然不能獲取右值的地址,但我可以像這里所做的那樣獲取右值引用的地址。

如果您可以對右值引用執行任何操作,而您可以對左值引用執行任何操作,那么用“&&”而不是“&”區分兩者有什么意義?

bar是右值還是左值?

這個問題自己回答。 任何有名字的都是左值(1) 所以bar是一個左值。 它的類型是“對string的右值引用”,但它是該類型的左值。

如果要將其視為右值,則需要對其應用std::move()


如果您可以對右值引用執行任何操作,而您可以對左值引用執行任何操作,那么用“&&”而不是“&”區分兩者有什么意義?

這取決於您對“執行操作”的定義。 左值引用和(命名的)右值引用在表達式中的使用方式幾乎相同,但它們在綁定到它們上的內容上有很大不同。 左值可以綁定到左值引用,右值可以綁定到右值引用(並且任何東西都可以綁定到對const的左值引用)。 也就是說,您不能將右值綁定到左值引用,反之亦然。

先說一個右值引用類型的function參數(比如你的bar )。 重要的不是bar是什么,而是您對bar所指的值的了解程度。 由於bar是一個右值引用,你肯定知道綁定到它的任何東西都是一個右值。 這意味着它一定會在完整表達式結束時被銷毀,並且您可以安全地將其視為右值(通過竊取其資源等)。

如果您不是直接對bar執行此操作的人,而只是想傳遞bar ,您有兩個選擇:要么您已完成bar ,然后您應該告訴下一個收到它的人它綁定到右值——執行std::move(bar) 或者你需要用bar做更多的事情,所以你不希望中間有人從你下面竊取它的資源,所以把它當作一個左值—— bar

總結一下:不同之處不在於您擁有參考資料后可以做什么。 不同之處在於可以綁定到引用的內容。


(1)一個很好的經驗法則,除了少數例外:枚舉數有名稱,但是是右值。 類、命名空間和 class 模板有名稱,但不是值。

bar 是右值還是左值

它是一個lvalue ,就像任何命名變量的表達式一樣。

如果您可以對右值引用執行任何操作,而您可以對左值引用執行任何操作,那么用“&&”而不是“&”區分兩者有什么意義?

您只能使用右值表達式初始化右值引用。 因此,您可以將一個臨時字符串傳遞給您的 function,但您不能在不顯式移動的情況下傳遞字符串變量。 這意味着您的 function 可以假設不再需要該參數,並且可以從中移開。

std::string variable;
foo(variable);            // ERROR, can't pass an lvalue
foo(std::move(variable)); // OK, can explicitly move
foo("Hello");             // OK, can move from a temporary

表達式bar是一個左值。 但它不是“對字符串的右值引用”。 表達式bar是一個左值引用。 您可以通過在 foo() 中添加以下行來驗證它:

cout << is_lvalue_reference<decltype((bar))>::value << endl; // prints "1" 

但我同意Angew的解釋rest。

一個右值引用,在它被綁定到一個右值之后,就是一個左值引用。 實際上它不僅適用於 function 參數:

string&& a = "some string";
string&& b = a; // ERROR: it does not compile because a is not an rvalue

如果您可以對右值引用執行任何操作,而您可以對左值引用執行任何操作,那么用“&&”而不是“&”區分兩者有什么意義?

右值引用允許我們在右值到期之前執行一些“左值操作”。

在這種情況下,命名 rvalue 引用是 lvalues ,而如果輸入類型是const 命名 rvalue 引用,那么它將是rvalue ,這是一個簡單的示例:

#include <string>
#include <iostream>

void foo(const std::string&& bar) { 
    std::string* temp = &bar; // compile error, can't get address
    std::cout << *temp << " @:" << temp << std::endl;
}

int main()
{
    foo("test");
    return 0;
}

希望這是有用的。

暫無
暫無

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

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