-3

哪个更便宜(内存和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

或者

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

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

每次迭代调用 .size() 方法成本高吗?

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

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

4

2 回答 2

4

您可以知道哪个更快的唯一方法是实际测量,即使那样,它也只会告诉您在一个特定平台上的一个特定实现,在一个特定的上下文中。一般来说,写你觉得最干净的,然后,如果你有一个性能问题,并且分析器说它是在这个位置发生的事情,尝试两个看看。

FWIW:问题是一种称为循环不变运动的优化:字面上调用函数(非内联)将比访问变量慢,至少在我能想象的任何架构上。但是编译器非常擅长识别循环中的常量表达式,并将它们提升出循环,将结果保存在寄存器中。它是否可以为调用执行此操作vt.size()至少部分取决于您在循环中执行的操作。特别是,如果您通过vt引用传递另一个翻译单元中的函数,并且编译器不进行跨单元优化,则编译器无法提升函数调用,因为被调用的函数可能会改变大小。当然,如果这样做,两个版本之间的时间差异不会很大,所以没关系。

编辑:

只是关于std::vector<>::size(): 在典型实现中的注释,它将类似于以下内容:

return endPtr - beginPtr;

, 其中entPtrbeginPtr是类型的成员变量 T*该函数几乎总是内联的,并且如果 编译器可以证明endPtr并且beginPtr不能更改循环中的值,它将被提升出循环(至少在激活优化时) 。如果循环很简单,它可能可以,并且两个版本的生成代码不会有任何差异。如果循环更复杂,它可能不能,但没关系,因为读取两个变量以及进行减法和除法的时间对于你在环形。

于 2013-05-09T08:08:24.997 回答
0

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

于 2013-05-09T08:02:55.867 回答