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

Why no CPU consumption during class instantiation?

本文关键字:CPU 消耗 实例化 为什么      更新时间:2023-10-16

我创建了一个循环,实例化一个类10亿次,并且非常惊讶地发现,根据Windows任务管理器,它在0毫秒内运行并且不消耗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亿次迭代,但不包含代码以保持帖子简洁),并且没有明显的差异。

请告知,谢谢!

更新:

问这个问题的原因是因为我经常使用composition,并且我有一个类的成员到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亿,这是正确的。通过这一点,我只能推断工作正在完成,对象正在被重用,这解释了我观察到的效率。

在"as-if "规则下,编译器被允许以任何它喜欢的方式转换你的程序,以使可观察到的副作用保持不变。您的程序除了返回0之外没有可观察到的副作用,因此几乎整个程序都可以被解析为零。

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

为了演示,如果我在Clang中编译你的代码,test函数的最终程序集如下:

_Z4testv:
    .cfi_startproc
    ret

它只是立即返回。

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

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