18 April 2023

C++ 核心指南目录

“Don’t depend on order of evaluation of function arguments”

理由

因为函数参数的求值顺序是未定义的行为。

注意

C++17 强化了求值顺序规则:一般都是从左到右,除了赋值操作是从右到左。但是没有定义函数参数列表的求值顺序规则。

例子

int i = 0;
void f(int a, int b) { cout << "a= " << a << ", b= " << b; }
int main()
{
    f(++i, ++i);
    return EXIT_SUCCESS;
}
a= 2, b= 1

在C++17之前,以上代码行为是未定义的。所以任何结果都有可能,比如 f(2, 2) 。从C++17开始,以上代码不能有未定义行为,但是没有指明哪个参数先求值。所以 f 的调用可能成了f(1, 2)也可能是f(2, 1),但是不同编译器可以自由选择以哪种方式求值。

例子

重载操作符可能导致求值顺序问题:

f1()->m(f2());          // m(f1(), f2())
cout << f1() << f2();   // operator<<(operator<<(cout, f1()), f2())

在C++17中,这个例子按照预期求值:从左到右。赋值操作从右到左。

f1() = f2();    // undefined behavior in C++14; in C++17, f2() is
                // evaluated before f1()

强化

好的代码分析工具能够提出告警