我对后增量和预增量运算符的返回值感到困惑。是否返回r值或l值。
#include<iostream>
using namespace std;
int main(){
int a=10;
cout<<++a++<<"\n";
}
以下代码给出了编译错误。
error: lvalue required as increment operator
为什么会出错?
编译器如何评估表达式++a++
?
答案 0 :(得分:7)
后增量表达式a++
的结果是 rvalue ;在递增之前具有a
值的临时值。作为 rvalue ,您可以使用其值,但不能修改它。具体来说,你不能像编译器那样应用预增量。
如果您要更改优先级以先执行预增量:
(++a)++
然后这将编译:预增量的结果是左值表示已被修改的对象。但是,这可能有不确定的行为;我不确定是否对这两个修改和值的各种用途进行了排序。
总结:不要试图编写带有多个副作用的棘手表达。
答案 1 :(得分:6)
从概念上讲,后缀++
的优先级高于前缀++
。
首先计算a++
。但这不是左值(因为它是a
的先前值)。因此它不能预先递增。因此编译器输出。
更重要的是,整个表达式++a++
的行为是未定义的,因为它们在表达式中没有排序点。
答案 2 :(得分:1)
只是为了它的价值(不是很多,IMO)如果你使问题a
成为正确的类型,那么可以通过编译和来定义行为。诀窍(在这种情况下,它是一个肮脏的,邪恶的技巧)是重载后修复增量运算符以返回左值:
class dirty_evil_trick {
int val;
public:
dirty_evil_trick() : val(0) {}
// to demonstrate, I'll just make postfix increment act like prefix increment.
dirty_evil_trick operator++(int) {
++val;
return *this;
}
dirty_evil_trick operator++() {
++val;
return *this;
}
operator int(){ return val; }
};
正如名称所暗示的,这是(至少在我看来)真正可怕的代码。我们已经使前缀和后缀增量运算符像前缀增量一样。因此,例如,如果我们按如下方式行使它:
int main(){
dirty_evil_trick a;
std::cout << ++a++;
}
...它应打印出2
。并且,由于调用运算符重载函数强加了排序约束,我们应该能够依赖所有符合编译器的结果。
我将再次重复:这不是关于如何编写代码的建议。它实际上只是演示了您所获得的错误消息,以及如何编写所做的实际上可以正常工作的代码。
答案 3 :(得分:0)
首先,这是一种糟糕的编程风格。根据您的需要,您可以轻松地写下:
++a;
cout << a++ <<"\n";
或
a++;
cout << ++a <<"\n";
出现编译错误......
由于运算符优先级,++a++
与++(a++)
相同。但是,a++
计算为右值。不允许在rvalue上使用前缀增量运算符。这类似于使用++10
,这是不合法的。