Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 右值和左值之间的精确差_C++_C++11_Rvalue - Fatal编程技术网

C++ 右值和左值之间的精确差

C++ 右值和左值之间的精确差,c++,c++11,rvalue,C++,C++11,Rvalue,当我在读书的时候,我得到了如下的嘲笑 // lvalues: // int i = 42; i = 43; // 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() i

当我在读书的时候,我得到了如下的嘲笑

// lvalues:
//
int i = 42;
i = 43; // 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
为什么int*p2=&foobar();是错误语句,而int*p1=&foo();这不是一个错误。后一个是左值,而前一个是右值


提前感谢

因此我们有两个功能:

int& foo();
int foobar();
  • foo
    是一个将左值引用返回int的函数
  • foobar
    是一个返回int的函数
函数调用表达式:

foobar()
foo()
两者都具有int类型(引用从表达式中删除,因此
foo()
具有int类型
int
,而不是
对int的左值引用)。这两个表达式具有不同的值类别:

  • foobar()
    是prvalue(对返回非引用的函数的函数调用是prvalue)
  • foo()
    是左值(对返回左值引用的函数的函数调用是左值)
不能获取右值的地址(prvalue是右值的一种),因此不允许使用
&foobar()


您可以获取左值的地址,这样就允许使用
&foo()

假设我们有下面用C显示的示例代码。它会编译吗?左值和右值的概念在这个问题中是如何工作的

#define X 8
int main(void)
{
    ++X; // will this line compile?
        return 0;

}
必须稍微解释一下左值和右值的概念,以便真正理解上面的代码以及所问的问题。在我们继续之前,您应该注意到这里给出的左值和右值的定义并不准确,因为即使是C标准本身在定义上也相当模糊

右值和左值之间的差异

对象是可以检查但不一定要修改的内存区域。左值是指此类对象的表达式。术语左值最初指出现在表达式左侧(因此为“l”)的对象。该定义不再适用,因为任何常量限定类型也被视为左值,但它永远不会出现在赋值语句的左侧,因为它无法修改。因此,术语“可修改的左值”是指可以修改的左值,常量限定类型不属于这一类

右值是任何具有值但不能指定值的表达式。也可以说右值是任何不是左值的表达式。右值的一个例子是一个文字常量,类似于“8”或“3.14”。显然,上面代码中的值“8”是一个右值

用我们对左值和右值的理解来回答这个问题

现在让我们试着解决这个问题。严格来说,前缀(或后缀)增量运算符的操作数必须是可修改的左值。那么,在上面的代码中,前缀增量运算符的操作数是多少


由于X是一个宏,在预处理器运行后,上面的语句将扩展到“++8”。这意味着“8”是前缀递增运算符的操作数。而且,由于8是右值,因此不能将其用作“++”的参数。这反过来意味着上面的代码将无法编译。

我相信你的最后一句话已经倒转了为什么不可能取foo的地址?@ss7don:你是说表达式
foo()
?你可以取
foo()的地址
。再次阅读我答案的最后一行。我接受了这个答案,因为它看起来合理。坦率地说,我仍然不理解foo和foobar之间的确切区别。两者都是函数。但是一个是右值,另一个是左值。@ss7don:值类别是表达式的属性,而不是函数的属性。值类别函数调用表达式的返回类型根据其返回类型计算。函数foo的返回类型为
int&
。函数foobar的返回类型仅为
int
。引用
&
的存在与否决定了对该函数的函数调用的值类别。谢谢。现在请tween值和函数消除了我的疑问。很好,但为什么要用这个例子呢?我不知道这样的问答题如何有助于理解这个问题。