与r值和l值混淆

时间:2015-09-07 09:39:36

标签: c++ c++11 lvalue rvalue

我最近在C ++ 11的白皮书上读过,如果我写的话,

void foo(X&)

这将被调用l值而不是r值

如果我写,

void foo(const X&)

这将同时调用r值和l值。

有人能举例说明这意味着什么吗?

4 个答案:

答案 0 :(得分:4)

此函数接受左值引用

void foo(X&)

并试图用右值调用它会产生错误。

此函数需要const左值参考

void foo(const X&)

但是有一个问题:

  

rvalue可用于初始化const左值引用,在这种情况下,rvalue标识的对象的生命周期将延长,直到引用范围结束。

来自cppreference

所以这最后一个函数同时接受左值和右值参数

struct X {};

void foo(X&) {
}

void fooC(const X&) {
}

int main() { 
   X obj;
   // foo(std::move(obj)); // Error - non-const
   foo(obj); // Valid
   fooC(obj); // Valid
   fooC(std::move(obj)); // Valid
}

有关详细信息,请查看此处:reference initialization或检查 [dcl.init.ref] / p5

答案 1 :(得分:1)

考虑以下代码:

script

什么是 echo '<script> run(); </scrit>'; ^^^^^^ ?这是一个字面常量

因此: echo '<script> run(); </script>';

int i = 58; 是一个r值(在这种情况下也是一个文字常量),因为你不能直接引用它,而且,让我们说,修改它,因为那里有&#39;没办法那样做。您可以参考58,因为它有一个名称,一个标识符,但foo (const int&)本身没有标识符。

通俗地说,如果某些东西存在但它没有声明的名称你可以访问它然后它是一个常数和一个r值,除非你用r-val引用int&amp;&amp;引用它,那么你可以改变它。

58

答案 2 :(得分:0)

当你声明foo函数时

void foo(X&)

然后这样的代码将无法编译:

foo(5);

但如果你宣布它:

void foo(const X&)

然后你可以这么称呼它:

foo(5);

const literal 5是一个r值,因为它没有名字。

答案 3 :(得分:0)

粗略地说,rvalues是临时对象(从函数返回),而lvalues也是你可以引用的对象。

例如:

X bar();

X x = bar();

在该代码中(忽略可能的编译器优化),创建一个临时X对象来保存返回的foo值并传递给x的copy-constructor,这个临时对象是一个rvalue,只存在于此语句并不能被代码的其他部分引用。 x然后是左值,您可以检索其地址并在以后引用它。

两个功能

void foo(X &);
void foo(const X &);

分别指望lvalues,non-const和const。后者接受rvalues的原因是因为rvalues可以转换为对lvalues的const引用。也就是说,你可以这样做:

const X &ref = bar();

此处由bar()返回的临时值在ref超出范围之前不会被销毁,因此它的生命周期已延伸到语句之外。但是你不能对非const引用做同样的事情,

X &ref = bar(); // Error!

这是不允许的,因为bar的返回值是临时值(rvalue)并且无法修改。

但是请注意,这不是C ++ 11的功能,这已经存在了。新功能是指定右值引用

的功能
void foo(X &&);
void foo(const X &&);

引入了更加微妙的情况,例如参见Universal References in C++11 - Scott Meyers