如果您使用调试器查看反汇编挡板,您可以看到生成的代码.对于VS2012 express在发布模式下你得到这个:
00AF1310 push edi
auto t0 = clock();
00AF1311 call dword ptr ds:[0AF30E0h]
00AF1317 mov edi,eax
auto r = g();
auto t1 = clock();
00AF1319 call dword ptr ds:[0AF30E0h]
cout << r << " time: " << t1-t0 << endl;
00AF131F push dword ptr ds:[0AF3040h]
00AF1325 sub eax,edi
00AF1327 push eax
00AF1328 call g (0AF1270h)
00AF132D mov ecx,dword ptr ds:[0AF3058h]
00AF1333 push eax
00AF1334 call dword ptr ds:[0AF3030h]
00AF133A mov ecx,eax
00AF133C call std::operator<<<:char_traits> > (0AF17F0h)
00AF1341 mov ecx,eax
00AF1343 call dword ptr ds:[0AF302Ch]
00AF1349 mov ecx,eax
00AF134B call dword ptr ds:[0AF3034h]
从前4行汇编中你可以看到两次调用时钟(ds:[0AF30E0h])在调用g之前发生.因此,在这种情况下,g取多长时间并不重要,结果只会显示这两个顺序调用之间的时间.
似乎VS已经确定g没有任何可能影响时钟的副作用,因此可以安全地移动呼叫.
正如Michael Petch在评论中指出的那样,将volatile添加到r的声明中将阻止编译器移动调用.