【问题标题】:C++11 lvalue, rvalue and std::move()C++11 左值、右值和 std::move()
【发布时间】:2016-01-14 08:26:44
【问题描述】:

我有以下代码:

#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&amp;&amp; 是右值引用,我想知道为什么test(std::move(a))test(b) 输出lvalue?它与签名匹配和函数重载有关吗?

【问题讨论】:

  • 你用的是什么编译器?输出应该是lvalue rvalue rvalue lvalue
  • @TartanLlama 我猜是 MSVC,它总是有问题。
  • @TartanLlama,我用的是Mac,编译器应该是LLVM的clang。

标签: c++ c++11 overload-resolution rvalue


【解决方案1】:

输出应该是:

lvalue.
rvalue
rvalue
lvalue.

右值表达式和右值引用类型的表达式之间有一个非常重要的区别。 b 的类型是对int 的右值引用,但表达式b 是左值;它是一个变量,你可以取它的地址。这就是为什么最后一行输出是lvalue 而不是rvalue。为了将其更改为右值,您应该在其上调用std::move

test(std::move(b));

【讨论】:

  • 酷,你是对的。我使用的 IDE 忽略了带有底层命令的“-std=c++11”选项,这导致我的输出与我发布的一样。我已经在终端中测试了代码,如果在没有“-std=c++11”选项的情况下编译,则会给出不希望的输出并带有警告。
【解决方案2】:

您可以阅读这篇文章,它很好地解释了它Universal References in C++11。另外值得一提的是,现在这些引用称为转发引用

在你的情况下,你有

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

第二种情况允许您在函数内部实现移动语义或完美转发。虽然第一个也允许,但只需要使用 std::move 即可将其值转换为右值。

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

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • @Mhd.Tahawi 我已将您的建议铭记于心 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 2020-11-10
  • 2015-07-15
  • 1970-01-01
  • 2015-09-12
  • 2021-08-26
  • 2020-05-25
相关资源
最近更新 更多