在vs2010 std :: vector.size()中:
return (this->_Mylast - this->_Myfirst);
和std :: vector.empty():
return (this->_Myfirst == this->_Mylast);
我的问题是,如果要检查矢量是否为零,那么这两个函数之间是否有任何不同的速度。 减去和等于几乎是相同的二进制操作,所以这两个函数的速度是相同的吗?
答案 0 :(得分:9)
除非你这样做并且每秒数百万次(而且严重的是,为什么会你?),否则它不会造成任何差别。
如果你真的有兴趣,请检查一下。设置几百万次的循环,看看每次循环的时间。
我想你会发现差异可以忽略不计。
如果专注于宏优化问题(例如算法选择)以及为可读性优化此类内容,您会好得多。
而且,无论如何,优化可读性是一种有效的方法,除非存在严重的性能瓶颈,否则我通常采用这种方法。换句话说,如果您根据其是否为空而执行某些操作,请使用empty()
或!empty()
。任何其他尺寸检查(如果其中至少有12个元素)应使用size()
(显然)。
作为一些微观优化无关紧要的例子,这里有一些C代码需要思考:
#include <stdio.h>
int main(void) {
int i, j, k, diff;
for (i = 0; i < 1000; i++)
for (j = 0; j < 1000000; j++)
//diff = (i == j);
diff = (i - j);
return 0;
}
当我使用默认优化(a)编译它,并使用time
命令运行它时,我得到CPU时间(超过五次运行),其中一行没有注释:
diff = (i - j) diff = (i == j)
============== ===============
2.488 2.216
2.424 2.220
2.452 2.224
2.484 2.152
2.464 2.152
===== =====
Avrgs: 2.463 2.193
现在第一个选项慢了12%,但有一件事需要你理解。虽然速度较慢,但仍需要两秒钟才能完成十亿次次。如果你这样做一次,差异在0.000000002463秒和0.000000002193秒之间,不值得优化。
选择你的战斗,瞄准你的优化。您可以通过宏优化策略获得大量速度提升。
(a)使用gcc
“疯狂”优化级别-O3
,它们都需要0.000秒(有时为0.004,但很少 - 我认为分辨率有限制time
命令),使差异更加无关紧要: - )
答案 1 :(得分:8)
使用empty()
优于size()
来检查矢量空白有两个原因:
std::vector.empty()
可能比std::vector.size()
更快,具体取决于具体实施方式。
使用empty()
检查向量空白比使用size()
更直观,更易读。
参考:
Nicolai M. Josutil的:
C ++标准库:教程和参考
指出:
<强> size()
强>
返回容器的实际元素数。
<强> empty()
强>
是检查元素数量是否为零(size()==0
)的快捷方式。
但是,empty()
可能会更有效地实现,因此您应该使用它
可能的。
请注意,为了确保哪一个更快,你必须为你的环境描绘两者。
答案 2 :(得分:5)
对于矢量,性能可能相同。即使它不相同,它也具有相同的Big O复杂性,并且速度的差异可以忽略不计。因此,如果您只想检查向量是否为空,则使用empty
可能更方便。它更准确地描述了您真正想要做的事情。
使用empty
的另一个原因是,当您稍后将容器更改为list
时,它可能具有更好的Big O复杂性。因为有std::list
个实现,其中size
具有线性复杂度,而空值始终为O(1)。
答案 3 :(得分:3)
Scott Meyers,在“有效STL”中,建议调用empty()
而不是检查所有容器的大小。他给出的原因是empty
对于所有标准包含都是恒定时间,而size
在某些列表实现中需要线性时间。
如果您使用尺寸而后来碰巧更换容器,则可能会出现性能问题。
因此,除非检查容器是否没有元素是一个真正的瓶颈(首先测量,如果存在问题,则进行优化),使用empty
。
答案 4 :(得分:2)
让我们停止制作:
bool empty_by_difference(int* b, int* e) {
return (e - b) == 0;
}
bool empty_by_equality(int* b, int* e) {
return e == b;
}
由Clang 3.0编译成以下IR:
define zeroext i1 @_Z19empty_by_differencePiS_(i32* %b, i32* %e) nounwind uwtable readnone {
%1 = icmp eq i32* %e, %b
ret i1 %1
}
define zeroext i1 @_Z17empty_by_equalityPiS_(i32* %b, i32* %e) nounwind uwtable readnone {
%1 = icmp eq i32* %e, %b
ret i1 %1
}
你可能不知道IR代表,但我认为这将会回家。
所以让我推测,基准只是浪费我的时间和你的时间。
现在,从语义的角度来看,我个人觉得阅读if (x.empty())
比阅读if (x.size() == 0)
更清楚。
在后一种情况下:
==
与!=
或<=
或>=
,... 0
是一种哨兵价值,与1
等其他任何价值都非常不同...... 答案 5 :(得分:1)
如果空白和尺寸之间存在差异,那么即使是基准也不会看到它。由于从C ++ 11开始,列表的大小为O(1),我认为写入大小然后为空更可读。但那只是我的观点:))
答案 6 :(得分:0)
减去和等于几乎是相同的二元操作
确实,几乎相同。但是AFAIK布尔运算符比其他运算符更快。
答案 7 :(得分:0)
应该没有速度差异。实际上,您应该看到为两种情况生成的完全相同的代码。 编译器应该能够执行以下转换:
if (vec.size() == 0)
// After inlining:
if (_Mylast - _Myfirst == 0)
// Equivalent to:
if (_Mylast == _Myfirst) // Which is the same as empty() after it is inlined