c++:函数左值或右值

Posted

技术标签:

【中文标题】c++:函数左值或右值【英文标题】:c++: function lvalue or rvalue 【发布时间】:2012-12-13 06:49:34 【问题描述】:

我刚开始通过阅读this page 了解 c++11 中的右值引用,但我被困在了第一页。这是我从该页面获取的代码。

  int& foo();
  foo() = 42; // ok, foo() is an lvalue
  int* p1 = &foo(); // ok, foo() is an lvalue

  int foobar();
  j = foobar(); // ok, foobar() is an rvalue
  int* p2 = &foobar(); // error, cannot take the address of an rvalue
    为什么foo() 是左值?是不是因为foo() 返回的int& 基本上是一个左值? 为什么foobar() 是右值?是因为foobar()返回int吗? 一般来说,您为什么要关心函数是否为右值?我想如果我阅读了那篇文章的其余部分,我会得到答案。

【问题讨论】:

【参考方案1】:

L-Values 是位置,R-Values 是 可存储 值(即,可以分配的值:例如,命名空间是 不可 可分配的;感谢 @ Maggyero 的编辑建议)。

所以:

    因为foo() 返回一个引用(int&),所以它本身就是一个左值。 正确。 foobar() 是一个右值,因为 foobar() 返回 int。 我们不太关心函数是否为 R 值。我们对 R-Value 参考感到兴奋。

你指的那篇文章很有趣,我之前没有考虑过转发或在工厂中使用。我对 R-Value 引用感到兴奋的原因是移动语义,例如:

BigClass my_function (const int& val, const OtherClass & valb);

BigClass x;
x = my_function(5, other_class_instance);

在该示例中,x 被销毁,然后 my_function 的返回值通过复制构造函数复制到 x 中。为了从历史上解决这个问题,你可以这样写:

void my_function (BigClass *ret, const int& val, const OtherClass & valb);

BigClass x;
my_function(&x, 5, other_class_instance);

这意味着现在my_function 有副作用,而且它不是那么容易阅读。现在,使用 C++11,我们可以改为:

BigClass & my_function (const int& val, const OtherClass & valb);

BigClass x;
x = my_function(5, other_class_instance);

让它像第二个例子一样高效地运行。

【讨论】:

‘R 值是实际值’ 更准确地说,R 值是 可存储 值。有些值不能在 C++ 中赋值,因此不是 R 值,例如一个类型,一个命名空间。 @Maggyero 命名空间和类型根本不是值。并非所有有名字的东西都是值 @Caleth 值是表达式的含义。由于命名空间和类型并非毫无意义,它们确实具有价值。你可以看看 Dana Scott 和 Christopher Strachey 在指称语义方面的工作。我不认为 C++ 的指称语义已经发布。目前,它仅在 ISO C++ 标准中以自然语言指定。 @Maggyero C++ 标准讨论了basic.lval 中的值,命名空间和类型不是表达式(尽管命名空间名称和类型名称可以与表达式一起出现)“glvalue 的结果是表示的实体纯右值的结果是表达式存储到其上下文中的值;类型为 cv void 的纯右值没有结果。结果为值 V 的纯右值有时被称为具有或命名为值 V。 " @Caleth 指称语义中的value(或denotation)在ISO C++ 标准的术语中称为entity。指称语义中的stored value(或存储的指称)在ISO C++ 标准中称为value。命名空间和类型是指称语义术语中的值,是 ISO C++ 标准中的实体。

以上是关于c++:函数左值或右值的主要内容,如果未能解决你的问题,请参考以下文章

& 返回左值或右值是啥?

C++左值右值和构造函数们

[转]C++11 左值右值右值引用详解

C++ 函数透明地采用左值和右值参数

C++左值左值引用右值右值引用

左值右值右值引用与move()forward()