将值缓存到变量或调用函数以返回值,这在C ++中更便宜?

时间:2013-05-09 07:51:28

标签: c++ optimization vector iteration

哪个更便宜(ram和cpu明智)?

/* caching */
vector<T> vt;
// ... populate the vector
typedef vector<T>::size_type v_t_type ;

vt_type size = vt.size();
for(vt_type i = 0; i < size; ++i)
  // ... do stuff with the vector

OR

/* pulling */
for(vt_type i = 0; i < vt.size(); ++i)
  // ... do stuff with the vector

不知道缓存和轮询是否是正确的术语,但示例应该是直截了当的。

每次迭代调用.size()方法代价是否昂贵?

让我们假设.size()做了一些简单的事情,比如从vt读取一个int成员变量。

在PHP和Javascript中,缓存通常比轮询便宜得多。

2 个答案:

答案 0 :(得分:4)

你能知道哪个更快的唯一方法就是实际 测量,即使那时,只会告诉你一个 在一个特定平台上的特定实现 特定背景。总的来说,写得最干净 给你,然后,如果你有性能问题,那么 分析师说,这是在做什么事情 位置,尝试两者,看看。

FWIW:问题是一种称为循环不变运动的优化: 字面上调用一个函数(没有内联)会慢于 访问变量,至少在我可以的任何架构上 想像。但编译器非常擅长识别常量 循环中的表达式,并将它们提升出循环, 将结果保存在寄存器中。是否可以做到这一点 致vt.size()的呼吁至少部分地取决于你 在循环中做。特别是,如果您通过引用传递vt 另一个翻译单元中的函数,编译器没有 做交叉单元优化,然后编译器不能提升 函数调用,因为被调用的函数可能会改变 尺寸。当然,如果你这样做,之间的时间差 这两个版本不会很重要,所以它并不重要。

编辑:

关于std::vector<>::size()的一个注释:典型的 实现,它将是:

return endPtr - beginPtr;

,其中entPtrbeginPtr是类型的成员变量 T*。该功能几乎总是内联的,并将被提升 离开循环(至少在激活优化时) if 编译器可以证明endPtrbeginPtr不能 改变循环中的值。如果循环很简单,那很可能 可以,并且生成的代码没有区别 这两个版本。如果循环更复杂,可能 不能,但这并不重要,因为时间阅读两者 变量,并且可能进行减法和除法 关于你所做的其他事情可以忽略不计 循环。

答案 1 :(得分:0)

STL的设计考虑了速度,因此编译器将内联size()。