1) Before calling a function, evaluate all parameters of the function.
2) Once a function starts to be executed, the expressions in the caller's function will not start to evaluate, or continue to evaluate until the execution of the called function ends, and the function will never be executed.
3) if the function parameter is an expression, these expressions can usually be evaluated in any order, including cross evaluation.
The F (expr1, expr2) compiler may evaluate expr1 or expr1 first, or cross the expr1 and expr2 values.
For f (G (expr1), H (expr2), expr1 must be evaluated before G () is called, expr2 must be evaluated before H () is called, G () and H () must be executed before F () is called. The values of expr1 and expr2 can be cross-valued.
A sequence point, definedProgramDuring execution, all the side effects of the expression before the point are completed before the program execution reaches the point. All the side effects of the expression after the point are, it does not occur when the program is executed to this point.
The expression (++ I) + (++ J) does not contain the sequence point. Therefore, the two "Side effects" of I ++ and J ++ first occur. According to the standard, is undefined. If the order point is added to this expression, for example:
; (++ I) + (++ J );
The standard only guarantees that these two side effects will occur before the entire expression is evaluated (that is, before the order point ";"), and will not occur before the previous statement is executed.
The standard also stipulates that the value of a certain expression between two adjacent sequence points can only be changed once at most. If the expression evaluate process changes the value of an object, the unique purpose of reading the value before the change must be to determine the new value to be saved.
For example, in the following expression, according to the standard, the execution result is undefined:
(I ++) + (I ++)
This expression itself does not contain any sequence point, but the evaluation of this expression, according to the definition of the operator, will change I twice, in violation of the "one change" requirement.
Let's look at the following expression. According to the standard, the execution result is also undefined:
X [I] = I ++
This expression does not contain any sequence point. Although the I value is changed only once, I is read from the left value of X [I, used to determine the subscript of the modified element in the array. This time, I ++ and I are definitely located between the same pair of sequence points. This expression changes the value of I during the evaluation process, reading I in X [I] is not used to determine the new value of I, which violates the "read can only be used to determine the new value" rule.
Any assumption of the order in which multiple side effects of expressions between adjacent sequence points are evaluated, or violation of the rules described in "one change, read is only used to determine new values"CodeThe execution results are all undefined. The "undefined" mentioned here is generally more serious than "unportable" and can be considered as an "Incorrect" Consent word.
We usually think that the standard definition of "ordered points" and Its semantics is to strictly define the expressions and evaluate processes of C/C ++, it is not intended to allow programmers to gain a grasp of the sequence points, or excessively exploit the side effects of expressions to evaluate values. In practice, we can introduce intermediate variables to avoid errors that are prone to "sequence points" and greatly reduce the "edge concept" of code readability ".
Sample
F (New T1, new T2)
The compiler generates code 1:
1) allocate memory for T1
2) construct T1
3) allocate memory for T2
4) construct T2
5) call f ()
If Step 3 or step 4 fails, the C ++ standard does not require T1 objects to be destroyed and the memory is released.
The compiler generates code 2.
1) allocate memory for T1
2) allocate memory for T2
3) construct T1
4) construct T2
5) call f ()
If Step 3 fails, T1 memory will be released, and the C ++ standard does not require the release of T2 memory. If Step 4 fails, T1 has been fully constructed, however, the C ++ standard does not require that the memory be destroyed and released.
Correct method:
Auto_ptr <t1> T1 (New T1 );
Auto_ptr <t2> T1 (New T2 );
F (T1, T2 );
In an expression, if other code may run out of an exception, do not allocate resources in this expression, even if the resources obtained through new are immediately managed in the same expression.