为什么在类实例化期间没有CPU消耗?

时间:2014-07-21 15:33:02

标签: c++

我创建了一个实例化类10亿次的循环,并且非常惊讶地看到它在0ms内运行并且根据Windows任务管理器没有消耗CPU时间。

正如您从下面的代码中看到的那样,我显然没有对默认构造函数做任何事情,但我假设会有一个重要的CPU命中,然后一遍又一遍地破坏该类。有人可以解释为什么没有明显的CPU命中?

class Cmytest {
public:
  int  lookup();
  bool create_rec();
  bool delete_rec();
};

void test() {
  for (int i=0; i<1000000000; i++) {
    Cmytest mytest;
  }
}

int main()
{
  test();
  return 0;
}

在运行上面的测试之后,我想看看如果我在两个不同的线程中运行test()将会发生什么(20亿次迭代,但不包括代码以保持简洁性)并且没有明显的差异。

请指教,谢谢!

更新:

问这个的原因是因为我经常使用构图,而且我有一个Cmytest成员的类。根据某些数据条件,Cmytest的成员将被执行,而在其他情况下,它什么都不做。这是一个长期运行的Web应用程序,我一直关注效率。

最终更新:

我决定让实例做一些事情(以确保它不仅仅是优化而忽略了什么都不做的循环)。我在这里看到了以下成员:

Cmytest::void count(int& i) {
  i++;
}

然后我在循环中调用它:

int iter=0;
void test() {
  for (int i=0; i<1000000000; i++) {
    Cmytest mytest;
    mytest.count(iter);
  }
}

结果是10亿,如果在两个线程中运行,那么20亿是正确的。通过这个,我只能推断工作正在进行,对象正在被重用,这解释了我观察到的效率。

2 个答案:

答案 0 :(得分:12)

在&#34; as-if规则&#34;下,编译器可以以任何方式转换您的程序,使得可观察的副作用保持不变†。除了返回0之外,您的程序没有任何可观察到的副作用,因此几乎整个程序都可以解析为空。

即使我们忽略了这一点,当一个对象在循环中声明时,编译器通常会反复重复使用同一个对象,而不必重新分配内存(但需要重新初始化对象)。在这个例子中,编译器甚至可以看到对象保持不变,可以重用,而不必重新初始化它。无论如何,你的班级无论如何都没有初始化的状态。

为了演示,如果我在Clang中使用最大优化编译代码,test函数的结果程序集如下:

_Z4testv:
    .cfi_startproc
    ret

它立即返回。

†​​复制elision是一种明确允许的优化,即使它确实修改了程序的可观察副作用。

答案 1 :(得分:2)

根据编译器和传递给它的标志,它可能决定优化不起作用的代码。在这种情况下,您声明一个从未使用过的变量,因此编译器决定优化此代码是安全的,因此它永远不会被执行。