std::vector::size() 是否比手动跟踪大小慢

Is std::vector::size() slower than keeping track of size manually?

本文关键字:跟踪 是否 size vector std      更新时间:2023-10-16

std::vector::size()每次调用时都会重新计算向量的大小,还是维护一个仅在修改向量时修改的计数器? 例如,如果我的类具有std::vector<double>成员,那么在单独的计数器中跟踪其大小是否有任何速度优势?

size()保证具有恒定的时间复杂度,并且在任何理智的实现中,操作将尽可能快。

this->_Mylast - this->_myFirst 

通常涉及两次内存提取。 如果在寄存器中维护计数,则可能会更快。 我说可能,因为在一个小循环中,减去的两个值将在缓存中,这并不总是比寄存器慢很多 - 取决于机器。 一个聪明的编译器,使用一个紧密的循环,无论如何都可以在寄存器中维护两者,如果它得到正确的数据流分析。 在一个不那么小的循环中,你永远不会注意到差异。 在寄存器中维护它意味着每次迭代需要额外的操作来更新寄存器,如果可以与其他操作并行完成,则可能是免费的,或者可能会花费一个指令周期。 因此,很难衡量差异。

无论如何,您的里程因处理器而异,即使 STL 的每个实现都有相同的size()代码。

没有必要在单独的计数器中跟踪它的大小,因为它是在向量内部完成的。这个函数上的代码是这样的:

iterator begin() {return start;}
iterator end() {return finish;}
size_type size() const { return size_type(end() - begin());}
iterator start;
iterator finish;

变量"start"、"finish"将在你推送或弹出元素后更改,因此函数 size() 只需要减号时间。如果使用单独的计数器,则在推送或弹出元素时也会有一个加号或减号。

否 - 只需使用 std::vector::size()

在 MSVC 上,它是this->_Mylast - this->_Myfirst实现的 - 您无法击败它。

正如其他人所说,它几乎不能变得更快。只有在矢量大小恒定的情况下,您确实可以通过使用此事实来节省一些 CPU 周期。实际上,您可以完全跳过查询大小。这对于渲染循环中经常重复的迭代等可能很重要。试想一下:

// reset vector of size=3 to value 10
for( size_t i=0; i < myvec.size(); ++i )
{
   myvec[i] = 10.0;
}

 myvec[0] = myvec[1] = myvec[2] = 10.0;

一个典型的用例是 3D 坐标向量、IP 地址等。但是准备好用你自己的例程替换一些在内部查询 size() 的 std::vector 例程。所以要点是,为了节省 CPU 周期,大小运算符不是目标,寻找其他逻辑位置。当你的矢量不改变它的大小时,即使是暂时的,你也有一只脚在门里挤出一些CPU周期。

PS:Valgrind是你的朋友,告诉你首先在哪里优化。事实上,大小运算符经常作为最佳候选者出现;至少对于某些算法。

祝你好运!

相关文章: