++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
.
++i;
- i
在语句中立即递增 1
,与 i++;
相反,1
递增是在语句之后完成的表达式.
i = i + 1;
- i
在语句中立即增加 1
。
i += 1;
- i
在语句中立即增加 1
。
这些表达式之间*是否存在任何差异,或者它们是否 100% 等效?
*"Any" 可能指语法和语义,也可能指性能和内存管理。
在 C 中,++i
等价于 (i += 1)
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
的性能稍微好一些,但这实际上取决于实现细节以及编译器的优化程度。性能和内存管理问题不在 language-lawyer 标签的范围内。
C
在 C 中,如果 i
是原子类型,i = i+1
和 i += 1
是不等价的,因为复合赋值是一个读取-修改-写入操作 memory_order_seq_cst
语义,根据 C 2018 6.5.16.2 3. 我也不能说 C 标准在 i = i+1
和 i += 1
的语义上完全清楚关于 volatile 对象。否则,++i
、i = i+1
和 i += 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++ 语义。
我真正关心的是++i;
、i = i + 1;
和i += 1;
的表达式是否100%等价,如果之前定义了i
.
++i;
-i
在语句中立即递增1
,与i++;
相反,1
递增是在语句之后完成的表达式.i = i + 1;
-i
在语句中立即增加1
。i += 1;
-i
在语句中立即增加1
。
这些表达式之间*是否存在任何差异,或者它们是否 100% 等效?
*"Any" 可能指语法和语义,也可能指性能和内存管理。
在 C 中,++i
等价于 (i += 1)
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
的性能稍微好一些,但这实际上取决于实现细节以及编译器的优化程度。性能和内存管理问题不在 language-lawyer 标签的范围内。
C
在 C 中,如果 i
是原子类型,i = i+1
和 i += 1
是不等价的,因为复合赋值是一个读取-修改-写入操作 memory_order_seq_cst
语义,根据 C 2018 6.5.16.2 3. 我也不能说 C 标准在 i = i+1
和 i += 1
的语义上完全清楚关于 volatile 对象。否则,++i
、i = i+1
和 i += 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++ 语义。