Pau*_*zak 6 c++ std visual-studio-2013
无论在发布模式下使用Visual Studio Professional 2013 Update 3编译时,无论使用32位还是64位选项,此代码示例都将输出:time: 0
N
#include <iostream>
#include <functional>
#include <ctime>
using namespace std;
void bar(int i, int& x, int& y) {x = i%13; y = i%23;}
int g(int N = 1E9) {
int x, y;
int r = 0;
for (int i = 1; i <= N; ++i) {
bar(i, x, y);
r += x+y;
}
return r;
}
int main()
{
auto t0 = clock();
auto r = g();
auto t1 = clock();
cout << r << " time: " << t1-t0 << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在rextester.com上使用gcc,clang和其他版本的vc ++进行测试时,它的行为正确且输出time
大于零.有什么线索在这里发生了什么?
我注意到内联g()
函数恢复了正确的行为,但更改了声明和初始化顺序t0
,r
而t1
不是.
如果您使用调试器查看反汇编挡板,您可以看到生成的代码.对于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<<<std::char_traits<char> > (0AF17F0h)
00AF1341 mov ecx,eax
00AF1343 call dword ptr ds:[0AF302Ch]
00AF1349 mov ecx,eax
00AF134B call dword ptr ds:[0AF3034h]
Run Code Online (Sandbox Code Playgroud)
从前4行汇编中你可以看到两次调用clock
(ds:[0AF30E0h]
)发生在调用之前g
.因此,在这种情况下,无论g
需要多长时间,结果只会显示这两个连续调用之间的时间.
似乎VS已经确定g
没有任何可能影响的副作用,clock
因此可以安全地移动呼叫.
正如Michael Petch在评论中指出的那样,添加volatile
到声明r
将阻止编译器移动调用.
归档时间: |
|
查看次数: |
346 次 |
最近记录: |