If you look at disassembling winddow using a debugger, you will see the generated code. For VS2012 Express in release mode, you will receive the following:
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]
from the first 4 lines of the assembly, you can see that two calls to clock ( ds:[0AF30E0h] ) occur before the call to g . Therefore, in this case it does not matter how long g takes, the result will only show the time between these two consecutive calls.
It seems that VS has determined that g has no side effects that would affect clock , so it's safe to move calls.
As Michael Patch notes in the comments, adding volatile to to the r declaration will stop the compiler from moving the call.
source share