3

为什么该代码由于错误而无法编译:

#include <iostream>

using namespace std;

int main()
{
    int i = 0; 
    cout << ++(i++) << " " << i << endl;
    return 0;
}

虽然该代码确实编译:

#include <iostream>

using namespace std;

int main()
{
    int i = 0; 
    cout << (++i)++ << " " << i << endl;
    return 0;
}

我不明白这个。从我的角度来看,编译第一个块是非常合理的。表达式 ++(i++) 仅表示取 i,将其递增并输出,然后再次递增。

我不是在询问 int 溢出中的未定义行为。在撰写问题时,我根本不知道 r 和 l 值,我也不关心为什么 ++i 被认为是 l 值,但 i++ 不是。

4

3 回答 3

8

这是因为后自增和前自增运算符返回不同类型的值。后增量的结果是一个所谓的“右值”,意思是它不能被修改。但是预增量需要一个可修改的值来增加它!

另一方面,前置增量的结果是一个左值,这意味着它可以被后置增量安全地修改。

上述规则的原因是后增量需要返回对象的值,就像在应用增量之前一样。顺便说一句,这就是为什么在一般情况下,在非内置对象上使用时,后增量被认为比前增量更昂贵。

于 2017-07-07T18:23:35.140 回答
2

简而言之,区别在于,在 C++ 中,您可以使用任意偶数个加号(仅受编译器限制)作为前缀增量运算符,如下所示

++++++++++++++++i;

后增量运算符只有两个优点

i++;

后缀增量运算符返回一个值(C++ 标准,5.2.6 增量和减量)

1 后缀 ++ 表达式的值是其操作数的值。[注:得到的值是原值的副本——尾注]

而前缀自增运算符在自增后返回其操作数(C++ 标准,5.3.2 递增和递减)

1 ...结果是更新后的操作数;它是一个左值...

与 C 中的 C++ 相反,您也可以使用前缀自增运算符仅对对象应用两个加号。:) 因此,C 编译器将针对这样的表达式发出错误

++++++++++++++++i;
于 2017-07-07T18:35:27.917 回答
1

当您使用 clang 编译它时,您会收到说明一切的错误消息。

<source>:8:13: error: expression is not assignable
cout << ++(i++) << " " << i << endl;

也许从 ++ 运算符开始会很好。实际上它是i = i + 1. 现在,如果我们查看后缀版本 i++,它在标准中表示它返回原始值的副本,并且随着side efect原始值的增加而增加。所以从 (i++) 你得到右值并试图分配给它,我们知道你不能分配给右值。

于 2017-07-07T18:58:47.840 回答