C++ 求值顺序
C++ Order of Evaluation
我想弄清楚 C++11 规范中是否有关于 re.以下代码 (GitHub link here) 的预期行为:
struct Scalar {
int data;
Scalar(int x) : data(x) {}
int get() {
return data;
}
Scalar &square() {
scale(data);
return *this;
}
void scale(int rhs) {
data *= rhs;
}
};
int main() {
Scalar v(3);
v.square().scale(v.get());
return v.data;
}
这主要是因为发现这在 g++
和 clang++
之间做了不同的事情:
$ g++ --version
g++ (GCC) 6.2.1 20160830
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ clang++ --version
clang version 3.9.0 (tags/RELEASE_390/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ g++ -std=c++11 order_of_ops.cpp -o a.out && ./a.out; echo $?
27
$ clang++ -std=c++11 order_of_ops.cpp -o a.out && ./a.out; echo $?
81
答案似乎应该在 n3242 的第 5.2.2 节和第 5.2.5 节中,但我无法找到具体的内容。
如果我没看错的话,你的代码的行为是未指定的。 C++11 引号的 N3337:
§ 1.9 [intro.execution] / 15
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced. [...]
If a side effect on a scalar object is unsequenced relative to either
another side effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
但紧随其后的是
Every evaluation in the calling function (including other function
calls) that is not otherwise specifically sequenced before or after
the execution of the body of the called function is indeterminately
sequenced with respect to the execution of the called
function.9
9) In other words, function executions do not interleave with each
other.
和
§ 5.2.2 [expr.call] / 8
[ Note: The evaluations of the postfix expression and of the
argument expressions are all unsequenced relative to one another. All
side effects of argument expression evaluations are sequenced before
the function is entered (see 1.9). —end note ]
因此,您对 Scalar::data
的修改和不相关阅读的顺序不确定。
话虽这么说,它很可能会改变并在 C++1z 中得到明确定义:
N4606 § 5.2.2 [expr.call] / 5
The postfix-expression is sequenced before each expression in the
expression-list and any default argument. The initialization of a
parameter, including every associated value computation and side
effect, is indeterminately sequenced with respect to that of any other
parameter.
因此,在 C++1z 中,您的 v.data
应该等于 81(如果我没看错的话)
我想弄清楚 C++11 规范中是否有关于 re.以下代码 (GitHub link here) 的预期行为:
struct Scalar {
int data;
Scalar(int x) : data(x) {}
int get() {
return data;
}
Scalar &square() {
scale(data);
return *this;
}
void scale(int rhs) {
data *= rhs;
}
};
int main() {
Scalar v(3);
v.square().scale(v.get());
return v.data;
}
这主要是因为发现这在 g++
和 clang++
之间做了不同的事情:
$ g++ --version
g++ (GCC) 6.2.1 20160830
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ clang++ --version
clang version 3.9.0 (tags/RELEASE_390/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ g++ -std=c++11 order_of_ops.cpp -o a.out && ./a.out; echo $?
27
$ clang++ -std=c++11 order_of_ops.cpp -o a.out && ./a.out; echo $?
81
答案似乎应该在 n3242 的第 5.2.2 节和第 5.2.5 节中,但我无法找到具体的内容。
如果我没看错的话,你的代码的行为是未指定的。 C++11 引号的 N3337:
§ 1.9 [intro.execution] / 15
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
但紧随其后的是
Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.9
9) In other words, function executions do not interleave with each other.
和
§ 5.2.2 [expr.call] / 8
[ Note: The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another. All side effects of argument expression evaluations are sequenced before the function is entered (see 1.9). —end note ]
因此,您对 Scalar::data
的修改和不相关阅读的顺序不确定。
话虽这么说,它很可能会改变并在 C++1z 中得到明确定义:
N4606 § 5.2.2 [expr.call] / 5
The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.
因此,在 C++1z 中,您的 v.data
应该等于 81(如果我没看错的话)