C++11 传递 POD 类型的值比常量引用差

C++11 pass by value of POD type worse than const reference

提问人:Fernando 提问时间:7/11/2017 更新时间:7/11/2017 访问量:760

问:

这个问题不是关于通过值或引用传递大型对象 - 也不是关于移动语义 - 就像许多其他问题一样。

我想知道 POD 类型必须有多小,以便按值而不是按常量引用传递它是一个更好的主意。我写了以下代码:

#include <ctime>
#include <iostream>
#include <complex>

using namespace std;

using Number = double; //complex<double>;

struct acc {
  Number a;
  void f(const Number& x) { a += x; }
  void g(Number x) { a += x; }
};

int main()
{
  int n = 1000000000;
  Number *v = new Number[n];

  for (int i = 0; i < n; i++) {
    v[i] = Number(i);
  }

  clock_t b, e;
  acc foo;

#ifdef _const
  b = clock();
  for (int i = 0; i < n; i++)
    foo.f(v[i]);

  e = clock();

  cout << ((double) e - b) / CLOCKS_PER_SEC << endl;
#else
  b = clock();
  for (int i = 0; i < n; i++)
    foo.g(v[i]);

  e = clock();

  cout << ((double) e - b) / CLOCKS_PER_SEC << endl;
#endif

  cout << foo.a << endl;

  return 0;
}

我用 gcc 编译而没有优化。

当使用 Number = complex 时,常量引用速度更快,我预计会有点。但是当使用 Number = double 时,通过常量引用的速度也更快,这完全让我感到惊讶(在我的计算机中,按值传递是 3.5,常量引用是 2.9)。

为什么会这样?在这么简单的例子中,包括内存访问在内的工作量不是一样吗?我必须编写一个模板库,我想小心并根据模板参数的大小使用 const 引用或按值传递,但现在我认为担心这一点是没有用的。还有人知道这是怎么回事吗?

如果我使用优化进行编译,那么这两个品种的运行速度相同。

C++ C++11 按引用传递

评论

15赞 juanchopanza 7/11/2017
"我用 gcc 编译,没有优化。这就是问题所在。不值得花太多时间担心未优化代码的相对性能。
1赞 DaOnlyOwner 7/11/2017
“如果我通过优化进行编译,那么两个品种的运行速度都一样快。”那么你想要什么?
2赞 n. m. could be an AI 7/11/2017
我投票结束这个问题,因为它没有提出任何明显的问题。
1赞 juanchopanza 7/11/2017
做你正在做的事情仍然完全没有意义。
2赞 geza 7/11/2017
比较未优化的构建是没有意义的。如果要对此进行比较,请使用优化,并使用避免内联的技术。就像把实现放在其他翻译单元中一样。或者使用特定于编译器的 noinline 属性。

答:

3赞 Yakk - Adam Nevraumont 7/11/2017 #1

编译器编写者并不关心未优化的玩具代码是否在一种类似情况下比另一种情况慢 20%。这就是原因。

你也不应该这样做,除非你处于一个极端的极端情况,你需要你的调试版本足够快,以满足一些软实时要求(比如,每 X Hz 完成一次渲染,或者在网络连接的另一端超时之前处理数据),并且 20% 的减速是关键路径。