Order of evaluation

本文详细介绍了C++中表达式的求值顺序及其规则,包括左值与右值计算、副作用顺序、以及可能引发未定义行为的情况。还探讨了序列点的概念及如何避免在程序中出现未定义行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

expression [ ik-spresh-uhn]  
noun
1.
the act of expressing or setting forth in words:  the free expression of political opinions.
Dictionary More Dictionary.com

Order of evaluation

Order of evaluation of the operands of any C++ operator, including the order of evaluation of function arguments in a function-call expression, and the order of evaluation of the subexpressions within any expression is unspecified (except where noted below). The compiler will evaluate them in any order, and may choose another order when the same expression is evaluated again.

There is no concept of left-to-right or right-to-left evaluation in C++, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() orf2() at run time.

Sequenced-before rules (since C++11)

Definitions

Evaluations

There are two kinds of evaluations performed by the compiler for each expression or subexpression (both of which are optional):

  • value computation: calculation of the value that is returned by the expression. This may involve determination of the identity of the object (glvalue evaluation, e.g. if the expression returns a reference to some object) or reading the value previously assigned to an object (prvalue evaluation, e.g. if the expression returns a number, or some other value)
  • side effect: access (read or write) to an object designated by a volatile glvalue, modification (writing) to an object, calling a library I/O function, or calling a function that does any of those operations.
Ordering

"sequenced-before" is an asymmetric, transitive, pair-wise relationship between evaluations within the same thread.

  • If A is sequenced before B, then evaluation of A will be complete before evaluation of B begins.
  • If A is not sequenced before B and B is sequenced before A, then evaluation of B will be complete before evaluation of A begins.
  • If A is not sequenced before B and B is not sequenced before A, then two possibilities exist:
    • evaluations of A and B are unsequenced: they may be performed in any order and may overlap (within a single thread of execution, the compiler may interleave the CPU instructions that comprise A and B)
    • evaluations of A and B are indeterminably-sequenced: they may be performed in any order but may not overlap: either A will be complete before B, or B will be complete before A. The order may be the opposite the next time the same expression is evaluated.

Rules

1) Each value computation and side effect of a full expression (an expression that is not part of another expression: the entire expression statement (ends with a semicolon), an initializer expression (ends with a comma or semicolon), controlling expression of a for/while loop, conditional expression of if/switch, the expression in a return statement (ends with a semicolon), etc) is sequenced before each value computation and side effect of the next full expression.

2) The value computations (but not the side-effects) of the operands to any operator are sequenced before the value computation of the result of the operator (but not its side-effects).

3) When calling a function (whether or not the function is inline, and whether or not explicit function call syntax is used), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.

4) The value computation of the built-in post-increment and post-decrement operators is sequenced before its side-effect.

5) The side effect of the built-in pre-increment and pre-decrement operators is sequenced before its value computation (implicit rule due to definition as compound assignment)

6) Every value computation and side effect of the first (left) argument of the built-in logical AND operator && and the built-in logical OR operator || is sequenced before every value computation and side effect of the second (right) argument.

7) Every value computation and side effect associated with the first expression in the conditional operator ?: issequenced before every value computation and side effect associated with the second or third expression.

8) The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compoundassignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (that is, before returning the reference to the modified object)

9) Every value computation and side effect of the first (left) argument of the built-in comma operator , is sequenced before every value computation and side effect of the second (right) argument.

10) In list-initialization, every value computation and side effect of a given initializer clause is sequenced before every value computation and side effect associated with any initializer clause that follows it in the brace-enclosed comma-separated list of initalizers.

11) A function call that is not sequenced before or sequenced after another function call is indeterminately sequenced(the program must behave as if the CPU instructions that constitute different function calls were not interleaved, even if the functions were inlined)

12) The call to the allocation function (operator new) is indeterminately sequenced with respect to the evaluation of the constructor arguments in a new-expression

Undefined behavior

1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

= +++ i++; // undefined behavior
= i++ + 1; // undefined behavior (but i = ++i + 1; is well-defined)
f(++i, ++i); // undefined behavior
f(= -1, i = -1); // undefined behavior

2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.

cout << i << i++; // undefined behavior
a[i] = i++; // undefined behavior

Sequence point rules (until C++11)

Definitions

Evaluation of an expression might produce side effects, which are: accessing an object designated by a volatile lvalue, modifying an object, calling a library I/O function, or calling a function that does any of those operations.

sequence point is a point in the execution sequence where all side effects from the previous evaluations in the sequence are complete, and no side effects of the subsequent evaluations started.

Rules

1) There is a sequence point at the end of each full expression (typically, at the semicolon)

2) When calling a function (whether or not the function is inline and whether or not function call syntax was used), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body

3) There is a sequence point after the copying of a returned value of a function and before the execution of any expressions outside the function.

4) Once the execution of a function begins, no expressions from the calling function are evaluated until execution of the called function has completed (functions cannot be interleaved)

5) In the evaluation of each of the following four expressions, using the built-in (non-overloaded) operators, there is a sequence point after the evaluation of the expression a.

&& b
|| b
? b : c
a , b

Undefined behavior

1) Between the previous and next sequence point a scalar object must have its stored value modified at most once by the evaluation of an expression, otherwise the behavior is undefined.

= +++ i++; // undefined behavior
= i++ + 1; // undefined behavior
= +++ 1; // undefined behavior (well-defined in C++11)
++ ++i; // undefined behavior (well-defined in C++11)
f(++i, ++i); // undefined behavior
f(= -1, i = -1); // undefined behavior

2) Between the previous and next sequence point, the prior value of a scalar object that is modified by the evaluation of the expression, must be accessed only to determine the value to be stored. If it is accessed in any other way, the behavior is undefined.

cout << i << i++; // undefined behavior
a[i] = i++; // undefined behavior

See also

  • Operator precedence which defines how expressions are built from their source code representation.
C documentation for  Order of evaluation

References

  • C++11 standard (ISO/IEC 14882:2011):
  • 1.9 Program execution [intro.execution]
  • 5.2.6 Increment and decrement [expr.post.incr]
  • 5.3.4 New [expr.new]
  • 5.14 Logical AND operator [expr.log.and]
  • 5.15 Logical OR operator [expr.log.or]
  • 5.16 Conditional operator [expr.cond]
  • 5.17 Assignment and compound assignment operators [expr.ass]
  • 5.18 Comma operator [expr.comma]
  • 8.5.4 List-initialization [dcl.init.list]
电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格和销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌和年份的电动汽车和插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售和安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商和车型组合,包括纯电动汽车和插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准和速度、价格、产地、自主水平、排放、安全等级、销售和保修。 时间跨度:模型跨度多年(包括传统和即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含不同的、特定于供应商的值(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km和额定值。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值