vector :: size()的性能:它是否与读取变量一样快?

zol*_*i2k 26 c++ gcc stl vector

我对一个大的整数向量进行了大量的计算.在计算过程中不会更改矢量大小.代码经常访问向量的大小.什么是更快的一般:使用vector::size()函数或使用辅助常量vectorSize存储向量的大小?我知道编译器通常能够size()在设置正确的编译器标志时内联函数,但是,使函数内联是编译器可以执行但不能强制执行的操作.

Mat*_* M. 16

有趣的问题.

那么,会发生什么?好吧,如果您使用gdb进行调试,您将看到类似3个成员变量的内容(名称不准确):

  • _M_begin:指向动态数组的第一个元素的指针
  • _M_end:指针超过动态数组的最后一个元素
  • _M_capacity:指针一个超过可以存储在动态数组中的最后一个元素

因此,实施vector<T,Alloc>::size()通常简化为:

return _M_end - _M_begin;  // Note: _Mylast - _Myfirst in VC 2008
Run Code Online (Sandbox Code Playgroud)

现在,在考虑可能的实际优化时,有两件事需要考虑:

  • 这个功能会被内联吗?可能:我不是编译器编写者,但这是一个不错的选择,因为函数调用的开销会使实际时间相形见绌,因为​​它是模板化的,我们在翻译单元中提供了所有代码
  • 将结果缓存(即具有未命名的局部变量):它可能是,但除非你反汇编生成的代码,否则你不会知道

换一种说法:

  • 如果你存储size自己,很有可能它会像编译器得到它一样快......
  • 但是你将自己暴露在维护残骸中:如果你突然修改了矢量并且不更新变量会怎样?)?

无论如何,我真的怀疑这是值得的麻烦.这是一个微观优化,并且不太可能产生很大的改进.

  • "结果会被缓存吗?" 即使在单一功能中,这个问题也可以有2个答案.编译器非常擅长确定是否以及在哪里有足够的寄存器来保存中间结果. (2认同)

sta*_*ica 11

据我了解1998 C++规范,vector<T>::size()需要恒定时间,而不是线性时间.因此,这个问题可能归结为读取局部变量比调用一个功能很少的函数更快.

因此,我声称将矢量存储size()在局部变量中会使程序加速一小部分,因为您只需调用该函数(因此执行所需的时间很少),而不是多次.

  • 我认为,如果你的编译器不够聪明,不能内联`vector :: size`,那么使用标准模板容器的任何代码的性能都会非常糟糕,因为删除一些调用`size`将无济于事.所以它不是真正的函数调用开销.如果是,那么对迭代器上的`operator []`或`operator*`的所有调用呢?我们可以假设它们也很慢,并使用以"&vec [0]"开头的指针迭代向量.如果你不相信你的`std :: vector`的实现,最好只用C而不是C++写... (2认同)

Mr.*_*Boy 9

vector :: size()的性能:它是否与读取变量一样快?

可能不是.

有关系吗

可能不是.

除非你每次迭代所做的工作很小(比如一个或两个整数运算),否则开销将是微不足道的.


Vik*_*ehr 5

在我所看到的每个实现中,看到vector::size()它都会减去end()begin(),即它没有读取变量那么快.

实现向量时,实现者必须在最快的元素之间做出选择,end()或者size(),在最后一个初始化元素之后将初始化元素的数量或指针/迭代器存储到元素之间.换一种说法; 使用迭代器进行迭代.

如果您担心size()性能,请像这样编写基于for循环的索引;

for (size_t i = 0, i_end = container.size(); i < i_end; ++i){
// do something performance critical
}
Run Code Online (Sandbox Code Playgroud)