3

我很好奇为什么链式静态函数和成员函数之间的参数评估顺序有所不同。从这个问题的答案中,我可以看到在这种链式函数调用之间的参数评估顺序是未指定的。以下面的代码片段为例:

#include <iostream>
class test {
public:
    static test& chain_s(test& t, int i) {
        std::cout << i << " ";
        return t;
    }

    test& chain(test& t, int i) {
        std::cout << i << " ";
        return *this;
    }
};

int main(int, char**) {
    int x = 2;
    test t;
    t.chain(t,++x).chain(t,++x).chain(t,++x);
    x = 2; std::cout << std::endl;
    t.chain_s(t,++x).chain_s(t,++x).chain_s(t,++x);

    return 0;
}

在 GCC 4.6.2 和 CL 15.00.30729.01 (MSVC 9) 的情况下,结果输出适合我

5 5 5
3 4 5

但是,我想知道规范中是否有任何原因,或者是否知道为什么静态函数从左到右(使用它们的参数)进行评估,而对于非静态函数,所有参数首先(右-从我在其他测试中看到的向左)。

我问这个的原因是因为我在尝试在 C 中获得类似行为(使用结构和函数指针)并失败时首先注意到这种行为差异。我强烈怀疑这是在 GCC 和 MSVC 中针对成员函数实现的一些优化,但我希望这里有人能对此有所了解。

编辑:
我忘了提到一个让我觉得奇怪的关键信息:GCC 只会警告链式非静态函数的未指定行为,而不是静态函数:

a.cpp: In function 'int main(int, char**)':
a.cpp:18:45: warning: operation on 'x' may be undefined [-Wsequence-point]

GCC 没有义务提供这样的警告,所以它可能会错过第二个表达式,但这就是让我相信一些有趣的事情正在发生的原因。

4

2 回答 2

2

您的代码具有未定义的行为,但我想您知道这一点。此外,您可以很容易地看到取决于优化标志的差异。但是在这种情况下,一个可能的原因是非静态函数需要三个参数,包括上一次调用的结果,而静态函数只需要两个,并且忽略上一次调用的结果。

于 2012-01-17T20:07:12.987 回答
2

没理由。就像您说的那样,语言未指定顺序。

使用从右到左顺序的一个原因是,具有可变数量参数的函数,例如printf,将始终将第一个参数放在顶部。否则没关系。

于 2012-01-17T19:27:38.817 回答