C++ 您能否复制或解释此Visual C++;和我在一起?

C++ 您能否复制或解释此Visual C++;和我在一起?,c++,visual-studio-2013,std,C++,Visual Studio 2013,Std,当在发布模式下使用Visual Studio Professional 2013 Update 3编译时,无论N的值是多少,都将输出time:0,32位和64位选项: #include <iostream> #include <functional> #include <ctime> using namespace std; void bar(int i, int& x, int& y) {x = i%13; y = i%23;} in

当在发布模式下使用Visual Studio Professional 2013 Update 3编译时,无论
N的值是多少,都将输出
time:0
,32位和64位选项:

#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;
}
#包括
#包括
#包括
使用名称空间std;
空条(inti,int&x,int&y){x=i%13;y=i%23;}
int g(int N=1E9){
int x,y;
int r=0;

对于(int i=1;i如果您使用调试器查看反汇编winddow,您可以看到生成的代码。对于处于发布模式的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]  
00AF1310推式edi
自动t0=时钟();
00AF1311呼叫dword ptr ds:[0AF30E0h]
00AF1317 mov edi,eax
自动r=g();
自动t1=时钟();
00AF1319呼叫dword ptr ds:[0AF30E0h]

执行此操作的时间可能低于调用clock()时Windows使用的计时器分辨率。我最近在这里写了一个答案,可能会让您了解在Windows上使用更高分辨率计时器的想法:这是一个优化问题(编译器认为调用g没有副作用)因此,它实际上会在调用
g
之前将这两个调用置于时钟。您应该能够通过将
auto r=g();
更改为
volatile auto r=g()来解决此问题;
@MichaelPetch你的
volatile
会阻止
g
在第二个
时钟之后移动,但是你也需要一些东西来阻止它在第一个
时钟之前移动,例如:
volatile n=42;volatile auto r=g(n);
@Paul No,对不起。想想
g()
作为计算2+2的东西。它可以在编译时计算,也可以在main开始时计算,或者在2
时钟之间计算,您所知道的只是它在存储到r中之前已经计算过了。为了澄清问题,可以使用类似于
volatile auto r=g()的语句
不必保持完整。编译器首先将其拆分为
auto tmp=g();volatile auto r=tmp;
第一部分可以随意移动,因为它没有副作用,也不依赖于任何东西。@Paul right。请注意,定义
n
的这一行可以在第一个
时钟之前或之后,这无关紧要。读取
n
的值是一个副作用,因此它不能与
clock
。由于
g
取决于该值,
g
必须在读取后保留。将
r
标记为
volatile
可能足以让编译器更改该行为。我希望这会起作用
volatile auto r=g()
合法吗?根据这个推理,几乎所有的计算都不会影响
时钟
,因此它可以被编译器移动到任何地方,但这绝对是一种疯狂。@MichaelPetch你是对的-就是这样-我会在答案中加上它。@MichaelPetch有一个合理的预期,即用户观察到的情况与此相同实际上,有一个要求。我只是查了C++编程语言,第四版,在第225页上读到:编译器可以重新排序代码以提高性能,只要结果与简单的执行顺序相同,那么调用你所经历的优化是合理的。bug.Volatile关键字的存在是为了向编译器提示不应该对变量(值、指针等)进行此类优化。使用优化会带来此类陷阱。这通常是大多数编译器允许您关闭某些优化或设置不同级别的原因。