为什么不同的C++编译器会为此代码提供不同的结果?

sor*_*h-r 1 c++ expression-evaluation visual-c++ unspecified-behavior

我正在编写一些C++代码,用于娱乐和练习,以了解有关语言功能的更多信息.我想更多地了解静态变量及其在递归函数中的行为.在g ++编译器中尝试此代码,我得到了预期的结果:

#include <iostream>
using namespace std;

int f(const int& value)
{
   static int result = 0;
   return result += value;
}

int main()
{
   cout << f(10) << ", " << f(f(10)) << ", " << f(f(f(10)));
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

但我的朋友在Microsoft Visual C++ 6中测试了相同的代码.输出是50, 80, 90我用其他C++编译器(g ++,Borland,Code :: blocks和MingW在Linux,Win和Mac下)输出测试的110, 100, 40.我无法理解输出如何50, 80, 90......

为什么MSVC的输出不同?

Jam*_*lis 14

以下三个子表达式的评估顺序未指定:

f(10)
f(f(10))
f(f(f(10)))
Run Code Online (Sandbox Code Playgroud)

编译器可以按任何顺序评估这些子表达式.您不应该依赖程序中特定的评估顺序,特别是如果您打算使用多个编译器进行编译.

这是因为该表达式中没有任何序列点.唯一的要求是在需要结果之前(即,在打印结果之前)评估每个子表达式.

在你的例子中,实际上有几个子表达式,我在这里标记为通过:

//   a  b     c       d  e f      g       h  i j k
cout << f(10) << ", " << f(f(10)) << ", " << f(f(f(10)));
Run Code Online (Sandbox Code Playgroud)

到通话operator<<(a,c,d,g,和h)都以被评估,因为每个取决于先前调用的结果.同样地,b具有前要评估a可以被评估,并k具有前进行评估j,i或h可被评估.

不过,也有一些子表达式之间没有相关性:结果b不依赖于结果k,所以编译器可以自由地生成评估代码k,然后b或b再k.

有关序列点和相关的未指定和未定义行为的更多信息,请考虑阅读Stack Overflow C++ FAQ文章"未定义的行为和序列点" (您的程序没有任何未定义的行为,但本文的大部分内容仍然适用).