简体   繁体   English

检查std :: vector的大小是否为零

[英]checking if a std::vector is of size zero

in vs2010 std::vector.size(): 在vs2010 std :: vector.size()中:

return (this->_Mylast - this->_Myfirst);

and std::vector.empty(): 和std :: vector.empty():

return (this->_Myfirst == this->_Mylast);

My question is if there is any speed different between this two functions, if you are going to check if a vector has zero elements. 我的问题是,如果要检查向量是否具有零元素,则这两个函数之间是否存在速度差异。 Minus and equal are almost the same binary operations right, so the speed is the same for both these functions? 负号和等于号几乎是相同的二进制运算,那么这两个函数的速度是否相同?

Unless you are doing this and millions of times a second (and seriously, why would you?), it won't make a scrap of difference. 除非您每秒进行数百万次此操作(认真地说,为什么会这样 ?),否则不会有任何不同。

If you're really interested, check it. 如果您真的有兴趣,请检查它。 Set up a loop of a few million times and see how long each takes. 建立一个数百万次的循环,看看每个循环需要多长时间。

I think you'll find that the difference is negligible. 我认为您会发现差异可以忽略不计。

You would be far better off concentrating on macro-optimisation issues, such as algorithm selection, and optimising this sort of stuff for readability. 将精力集中在宏优化问题(例如算法选择)上并优化此类内容以提高可读性会更好

And, in any case, optimising for readability is a valid approach, and one I usually take unless there are serious performance bottlenecks. 而且,无论如何,针对可读性进行优化是一种有效的方法,除非存在严重的性能瓶颈,否则我通常会采用这种方法。 In other words, use empty() or !empty() if you're doing something based on whether or not it's empty. 换句话说,如果您要根据是否为空来执行某些操作,请使用empty()!empty() Any other size check (like if there's at least twelve elements in it) should use size() (obviously). 任何其他大小检查(例如其中是否至少包含十二个元素)都应使用size() (显然)。

As an example of how irrelevant some micro-optimisations can be, here's some C code to ponder: 作为一些微优化可能无关紧要的示例,下面是一些需要考虑的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;
}

When I compile that with default optimisation (a) , and run it with the time command, I get CPU times of (over five runs), with one of those lines uncommented: 当我使用默认优化(a)进行编译并使用time命令运行它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

Now that first option is 12% slower but there's one thing you need to understand. 现在,第一种选择的速度要慢12%,但是您需要了解一件事。 Even though it's slower, it still only took two seconds to do this a billion times. 尽管速度较慢,但​​仅需两秒钟即可完成十亿次。 If you're doing it once, the difference is between 0.000000002463 seconds and 0.000000002193 seconds, not really worth the effort of optimising. 如果只执行一次,则差异在0.000000002463秒和0.000000002193秒之间,这确实不值得进行优化。

Pick your battles, target your optimisations. 选择您的战斗,针对您的优化。 You can get massive speed improvements with macro-optimisation strategies. 通过宏优化策略,您可以大幅度提高速度。


(a) With gcc "insane" optimisation level -O3 , they both take 0.000 seconds (sometimes 0.004, but rarely - I gather there's a limit to the resolution of the time command), making the difference even more irrelevant :-) (a)使用gcc “疯狂”优化级别-O3 ,它们都需要0.000秒(有时是0.004,但是很少-我认为time命令的分辨率存在限制),这使得差异变得更不相关了:-)

There are two reasons for using empty() over size() for checking vector emptyness: 使用size() empty() size()来检查向量空度有两个原因:

  • std::vector.empty() may be faster than std::vector.size() depending on implementations. 根据实现的不同, std::vector.empty() 可能std::vector.size() 更快

  • Using empty() for checking vector emptyness is more intutive and readable than using size() . 与使用size()相比,使用empty()检查向量的空度更直观,更易读。


Reference: 参考:
Nicolai M. Josutil's: Nicolai M.Josutil的:
The C++ Standard Library: A Tutorial and Reference C ++标准库:教程和参考

which states: 指出:

size()
Returns the actual number of elements of the container. 返回容器的实际元素数。

empty()
Is a shortcut for checking whether the number of elements is zero ( size()==0 ). 是检查元素数是否为零( size()==0 )的快捷方式。 However, empty() might be implemented more efficiently, so you should use it if possible. 但是, empty()可能会更有效地实现,因此,如果可能,应使用它。


Note though that to be absolutely sure of which one is faster, You will have to profile both for your enviornment. 请注意,尽管要绝对确定哪一个速度更快,但您必须为您的环境配置两者。

For vector the performance is probably the same. 对于vector,性能可能是相同的。 Even if it is not the same it has same Big O complexity and the difference in speed is negligible. 即使不一样,它也具有相同的Big O复杂度,并且速度差异可以忽略不计。 So it is probably more convenient to use empty if you only want to check that the vector is empty. 因此,如果只想检查向量是否为空,则使用empty可能更方便。 It describes more accurately what you really want to do. 它更准确地描述了您真正想要做什么。

Another reason to use empty is that when you later change the container to list , it may have better Big O complexity. 使用empty另一个原因是,当您以后将容器更改为list ,它的Big O复杂度可能会更高。 Because there are some std::list implementations where size has linear complexity while empty is always O(1). 因为有一些std::list实现,其中size具有线性复杂度,而空则始终为O(1)。

Scott Meyers, in "Effective STL", recommends calling empty() instead of checking the size for all containers. Scott Meyers在“有效的STL”中,建议调用empty()而不是检查所有容器的大小。 The reason he gives is that empty is constant-time for all the standard containters, whereas size takes linear time in some list implementations. 他给出的原因是,对于所有标准容器而言, empty是恒定时间,而在某些列表实现中, size需要线性时间。

If you use size and you happen to change your container later, a performance problem could arise. 如果使用大小,并且稍后碰巧要更改容器,则可能会出现性能问题。

So, unless checking if the container has no elements is a real bottleneck (measure first, optimize if there is a problem), use empty . 因此,除非检查容器是否没有元素是一个真正的瓶颈(首先测量,如果问题就进行优化),请使用empty

Let's stop the fabulations here: 让我们这里停止虚构

bool empty_by_difference(int* b, int* e) {
  return (e - b) == 0;
}

bool empty_by_equality(int* b, int* e) {
  return e == b;
}

Is compiled by Clang 3.0 into the following IR: 由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
}

You may not know the IR representation, but still I think this will strike home. 您可能不知道投资者关系代表,但我仍然认为这会奏效。

So let me speculate than a benchmark is just a loss of my time, and yours. 因此,让我推测,基准测试只是我和您的时间的损失。


Now, from a semantic point of view, I personally find it clearer to read if (x.empty()) than to read if (x.size() == 0) . 现在,从语义的角度来看,我个人发现读取if (x.empty())比读取if (x.size() == 0)更清晰。

In the latter case: 在后一种情况下:

  • my eyes have to work more: distinguishing == from != or <= or >= , ... 我的眼睛需要做更多的工作:将==!=<=>=区别开...
  • my brain has to work more: remembering than 0 is a kind of sentinel value, very different from any other value such as 1 etc... 我的大脑需要做更多的工作:记住大于0是一种前哨值,与任何其他值(例如1等)有很大的不同...

If there is a different between empty and size its so small not even a benchmark will see it. 如果空值和大小之间存在差异,那么它甚至很小,甚至基准测试都不会看到它。 Since size is O(1) for list starting from C++11 I think its more readable to write size then empty. 因为从C ++ 11开始,列表的大小为O(1),所以我认为写入大小更可读,然后为空。 But thats just my opinion:) 但那只是我的个人意见:)

Minus and equal are almost the same binary operations right 减号和等于几乎是相同的二进制运算

Indeed, almost the same. 确实, 几乎一样。 But AFAIK boolean operators are faster than other operators. 但是AFAIK布尔运算符比其他运算符要快。

There should be no speed difference. 不应有速度差异。 In fact you should see the exact same code generated for both cases. 实际上,您应该看到两种情况下生成的代码完全相同。 The compiler should be able to perform the following transformations: 编译器应该能够执行以下转换:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM