2012-01-17 141 views
3

我很好奇为什么在链接静态函数和成员函数之间的参数计算顺序的差别。从this question的答案我可以看出它没有说明在这样的链接函数调用之间参数评估顺序是什么。举个例子下面的代码片断:评估顺序调用

#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没有义务提供这样的警告,因此可能会错过第二个表达式,但是这是使我相信一些有趣的事情是怎么回事。

+0

肯定这样的事情应该是不相关的任何代码,你写... – 2012-01-17 19:38:00

+0

是的,但我想知道为什么一些代码是错误的,但不会产生警告,当在类似的情况下,它会。 – harrbharry 2012-01-17 19:48:57

回答

2

没有理由。就像你说的那样,这个顺序并没有被语言所指定。

使用从右到左的顺序

原因之一是,与可变数量的参数,如printf功能,然后将总是具有在顶部的第一参数。否则它并不重要。

+0

我忘了问为什么编译器输出的消息不同,有关于此的任何想法?这也是导致整个问题的原因。 – harrbharry 2012-01-17 19:50:51

+0

即使使用'printf',编译器也可以按任意顺序评估参数,甚至交织评估结果。在基于堆栈的机器上,第一个参数可能是最后一个参数,但编译器也很有可能在堆栈中保留必要的空间,并使用sp相对寻址存储它所属的每个参数。以任何顺序发布都很方便。 – 2012-01-17 20:09:50

2

你的代码是未定义行为,但我想你知道。另外,根据优化标志,您可以轻松看到差异。但 在这种情况下,其中一个可能的原因是,非静态函数需要 三个参数,其中包括前一个调用的结果,其中作为 的静态函数只需要两个,并且前一个 调用的结果被忽略。