后缀(前缀)自增,左值和右值(在 C 和 C++ 中)

5
我刚学到了以下事实:
前缀增量(++var_name)在C中是一个R值(至少,我确定它不是C中的L值),但在C++中它是一个L值。
后缀增量(var_name++)在C中是一个R值(至少,我确定它不是C中的L值)。这也适用于C++(它说结果是一个prvalue)。
我在VS2010(.cpp和.c)和Ubuntu(gcc和g++)中进行了检查。
在C++标准http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf的p.109(5.3.2)中,写道

前缀 ++ 的操作数通过加1进行修改,或者如果它是 bool 类型,则设置为 true(此用法已被弃用)。 操作数必须是可修改的左值。 操作数的类型必须是算术类型或指向完全定义的对象类型的指针。 结果是更新后的操作数;它是一个左值,...

在第101页中,(5.2.6)

后缀 ++ 表达式的值是其操作数的值。...结果是 prvalue。 结果的类型是操作数类型的 cv-unqualified 版本。另请参见 5.7 和 5.17。

(我不知道 R-value 和 prvalue 之间的区别,但是)关于 C 标准 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf,前缀 ++ 描述在 6.5.3.1 中,后缀 ++ 描述在 6.5.2.4 中,但从描述中,我无法得到清晰明确的答案。

我想知道它们成为R值或L值的原因。我所知道的是,我们可以将值赋给(可修改的)L值,例如变量名。R值是表达式的值。但我不知道后缀++在C和C ++中为什么不是L值,以及为什么前缀++在C中不是L值的细节。(我看到过像“后缀++...存储...在临时地址中,然后...”这样的东西,但我还是不明白)。另一个问题是为什么C和C ++中的前缀++不同?使前缀++成为L值(在C ++中)有很多优点吗?如果是这样,为什么C不改变呢?(除了向后兼容之外的其他原因,或者至少为什么更改会引起很多问题)。

你说你在VS2010和gcc中检查了你的假设。你用什么代码来验证这些问题的假设? - Brandin
"我看到过类似于“后缀++...将...存储在临时地址中”,但我仍然不理解" - 如果您引用您不理解的标准中的整个句子,也许有人可以为您澄清。 - Brandin
此外,仅使用类似 (a++) = 3(++a) = 3 的语句。 - user565739
那个标准(N3242)相当老了。 - Shoe
这是在2011年。它已经过时了吗? - user565739
显示剩余3条评论
2个回答

1

确实如此

  • 前置自增/自减运算符 (++var 或 --var) 会产生一个左值(即可修改的对象)

  • 后置自增/自减运算符 (var++ 或 var--) 会产生一个右值(即临时对象)。

考虑以下使用前置自增/自减运算符的代码

{

int i = 0;

int* pi = &(++i);

}

“其实它的伪代码是这样的”,保留html格式。
i = i+1; // pre increment i

int* pi = &i; // then evaluate its address and assign it to pi 

现在考虑同样的代码,但使用后置递增/递减运算符,并且如果编译器接受了这个无效的代码会产生什么后果。
{

int i = 0;

int* pi = &(i++); // Not OK !! because it is a temporary variable

}

它的伪代码将是:
int i = 0;

int tmp = i; // compiler creates a temporary variable to save value of i

int* pi = &tmp; // then would take the address of a temporary variable 

i = i + 1; 

1
C和C++是不同的语言。C++具有运算符重载,而C没有。无论是前缀还是后缀,++操作符都可以在C++中重载。C++还具有引用,而C没有。
在C中,++ii++都产生一个不是lvalue的值。这是可取的,否则你可能会因为试图在同一序列点边界内修改同一标量而遭受未定义的行为。
发人深省:在C中,逗号运算符也会产生一个不是lvalue的值,所以为了“丢弃”lvalueness,你可以这样做:
(0, lvalue)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接