簡體   English   中英

C ++ 11 lvalue,rvalue和std :: move()

[英]C++11 lvalue, rvalue and std::move()

我有以下代碼:

#include <iostream>
using namespace std;
void test(int& a) {
    cout << "lvalue." << endl;
}
void test(int&& a) {
    cout << "rvalue" << endl;
}
int main(int argc, char *argv[]) {
    int a = 1;
    int&& b = 2;
    test(a);
    test(1);
    test(std::move(a));
    test(b);
}

哪個輸出:

lvalue.
rvalue
lvalue.
lvalue.

std::move()int&&是rvalue引用,我想知道為什么test(std::move(a))test(b)輸出lvalue 它與簽名匹配和函數重載有關嗎?

輸出應該是:

lvalue.
rvalue
rvalue
lvalue.

在rvalues和類型為rvalue引用的表達式之間存在非常重要的區別。 b的類型是對int的rvalue引用,但表達式b是左值; 它是一個變量,你可以把它的地址。 這就是輸出的最后一行是lvalue而不是rvalue 要將其更改為右值,您應該在其上調用std::move

test(std::move(b));

你可以閱讀這篇文章,它很好地解釋了C ++ 11中的Universal References 還值得一提的是,現在這些引用稱為轉發引用

在你的情況下,你有

void test(int& a); // lvalue reference overload
void test(int&& a); // rvalue reference overload

第二種情況允許您在函數內實現移動語義或完美轉發。 雖然第一個也允許它,但只需要使用std::move ,它將其值轉換為rvalue。

test(a);
test(1);
test(std::move(a));
test(b);
  • a有一個名稱,所以默認將移動語義應用到它將是危險的混淆和容易出錯,因為我們剛剛移動的東西仍然可以在后續的代碼行中訪問。

  • 1沒有名字,你可以拿它的地址,所以它是一個右值。

  • std::move(a)使用std::move你把這個給右值,你應該記住它,當你使用a下一次。

  • ba相同 - 它有一個名字,你可以取它的地址。

左值和右值的一些例子:

// lvalues:
//
int i = 42;
i = 43; // ok, i is an lvalue
int* p = &i; // ok, i is an lvalue
int& foo();
foo() = 42; // ok, foo() is an lvalue
int* p1 = &foo(); // ok, foo() is an lvalue

// rvalues:
//
int foobar();
int j = 0;
j = foobar(); // ok, foobar() is an rvalue
int* p2 = &foobar(); // error, cannot take the address of an rvalue
j = 42; // ok, 42 is an rvalue

暫無
暫無

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

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