++i, i = i + 1 和 i += 1 等价于 C/C++ 吗?

Are ++i, i = i + 1 and i += 1 equivalent in C/C++?

我真正关心的是++i;i = i + 1;i += 1;的表达式是否100%等价,如果之前定义了i .

  1. ++i; - i 在语句中立即递增 1,与 i++; 相反,1 递增是在语句之​​后完成的表达式.
  2. i = i + 1; - i 在语句中立即增加 1
  3. i += 1; - i 在语句中立即增加 1

这些表达式之间*是否存在任何差异,或者它们是否 100% 等效?

*"Any" 可能指语法和语义,也可能指性能和内存管理。

在 C 中,++i 等价于 (i += 1)

C11 Draft Standard 6.5.3.1p2:

The expression ++E is equivalent to (E+=1).

表达式 i += 1 等同于 i = i + 1, 除了 在第一种情况下 i 保证只计算一次.在函数调用中,i += 1 产生单次求值。

C11 Draft Standard 6.5.16.2p3:

A compound assignment of the form E1 op = E2 is equivalent to the simple assignment expression E1 = E1 op (E2), except that the lvalue E1 is evaluated only once, and with respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. If E1 has an atomic type, compound assignment is a read-modify-write operation with memory_order_seq_cst memory order semantics.

考虑到 i 在此表达式中仅计算一次,您可能希望 ++i 的性能稍微好一些,但这实际上取决于实现细节以及编译器的优化程度。性能和内存管理问题不在 标签的范围内。

C

在 C 中,如果 i 是原子类型,i = i+1i += 1 是不等价的,因为复合赋值是一个读取-修改-写入操作 memory_order_seq_cst 语义,根据 C 2018 6.5.16.2 3. 我也不能说 C 标准在 i = i+1i += 1 的语义上完全清楚关于 volatile 对象。否则,++ii = i+1i += 1 是等效的,因为 i 只是一个标识符,而不是任何更复杂表达式的占位符。

C++

在 C++ 中,操作是不等价的。证明:

这个程序:

#include <iostream>


class SensitiveToOperations
{
public:
    SensitiveToOperations operator ++() { std::cout << "Preincrement.\n"; return *this; }
    SensitiveToOperations operator +(int that) const { std::cout << "Addition.\n"; return *this; }
    SensitiveToOperations operator =(SensitiveToOperations that) { std::cout << "Assignment.\n"; return *this; }
    SensitiveToOperations operator +=(int that) { std::cout << "AdditionAssignment.\n"; return *this; }
};


int main(void)
{
    SensitiveToOperations i;
    ++i;
    i = i + 1;
    i += 1;
}

产生这个输出:

Preincrement.
Addition.
Assignment.
AdditionAssignment.

由此可见,不同的操作可能会得到不同的结果。

对于基本类型,操作可能在很大程度上是等价的,但我没有资格谈论关于 atomic 或 volatile 的 C++ 语义。