C++ 向量中的 size() 与 empty() - 为什么 empty() 是首选?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/743197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
size() Vs empty() in vector - why empty() is preferred?
提问by aJ.
While debugging something, I saw the STL vector::empty() implementation:
在调试某些东西时,我看到了 STL vector::empty() 实现:
bool empty() const
{return (size() == 0); }
I believe, whenever we are probing the emptiness of vector it is always recommended to use empty over size(). But seeing that implementation, I am wondering, what is the benefit of doing so? Instead, there is a function call overhead in calling empty as it internally calls size()==0.
我相信,每当我们探索 vector 的空性时,总是建议使用 empty over size()。但是看到那个实现,我想知道这样做有什么好处?相反,在调用 empty 时会产生函数调用开销,因为它在内部调用 size()==0。
I thought empty() may be helpful in case of list as size() doesn't guarantees the constant time in list. To verify my assumption, I checked the list implementation and surprisingly, found the same implementation in list as well,
我认为 empty() 在列表的情况下可能会有所帮助,因为 size() 不能保证列表中的恒定时间。为了验证我的假设,我检查了列表实现,令人惊讶的是,在列表中也发现了相同的实现,
return (size() == 0);
I am bit confused now. If empty internally uses size() then why should we prefer empty over size() ?
我现在有点困惑。如果 empty 内部使用 size() 那么为什么我们更喜欢 empty 而不是 size() ?
采纳答案by dirkgently
You would need to write the condition out everytime you use size()
. It's convenient to use empty()
. This is of course, provided you don't switch containers. As others have pointed out, it is upto the implementation to use size()
in empty()
or not. However, the standard does guarantee that: empty()
is a constant-time operation for all
standard containers.
每次使用时都需要写出条件size()
。使用起来很方便empty()
。当然,前提是您不切换容器。正如其他人所指出的那样,它是高达执行使用size()
中empty()
或没有。但是,该标准确实保证:empty()
是所有标准容器的恒定时间操作。
回答by Artyom
Because if you switch from std::vector to std::list or other container, it may be different.
因为如果从 std::vector 切换到 std::list 或其他容器,可能会有所不同。
For example some implementations of std::list::size
take O(n)
and not O(1)
.
例如std::list::size
takeO(n)
和 not 的一些实现O(1)
。
回答by Chris Jester-Young
Well, as you say, that's just an implementation detail. std::list
can be implemented either with a stored size (constant-time size()
but linear-time splice()
), or without (constant-time splice()
but linear-time size()
). By choosing to use empty()
, you avoid betting on an implementation detail, when you don't need to know the size.
好吧,正如你所说,这只是一个实现细节。std::list
可以使用存储大小(常量时间size()
但线性时间splice()
)或不使用(常量时间splice()
但线性时间size()
)来实现。empty()
当您不需要知道大小时,通过选择使用,您可以避免押注于实现细节。
回答by David Rodríguez - dribeas
Following the standard, empty() should be preferred as it has constant time complexity regardless of the container type.
遵循标准,应首选 empty() ,因为无论容器类型如何,它都具有恒定的时间复杂度。
In C++03 standard, chapter 23.1, table 65: Container Requirements
在 C++03 标准中,第 23.1 章,表 65:容器要求
Operation: empty()
Return_type: convertible to bool
Semantics: equivalent to size()==0
Complexity: constant
It seems as if in your STL implementation, they took the semantics as the real implementation ignoring the complexity requirements, or size() is constant time in the implementation (stored field).
似乎在您的 STL 实现中,他们将语义作为真正的实现而忽略了复杂性要求,或者 size() 是实现中的常量时间(存储字段)。
If size() is not constant time, contact your vendor about std::list<>::empty() not fulfilling the standard container requirements.
如果 size() 不是恒定时间,请就 std::list<>::empty() 不满足标准容器要求与您的供应商联系。
回答by gnud
1st, using a function called empty()
when you want to know if something is empty makes code more readable, and means you don't have to worry about implementation details. It also means that your code can more easily be adapted to other types of containers, with other characteristics.
第一,empty()
当你想知道某个东西是否为空时,使用一个被调用的函数会使代码更具可读性,这意味着你不必担心实现细节。这也意味着您的代码可以更容易地适应具有其他特征的其他类型的容器。
2nd, that's just one STL implementation. My GNU C++ one looks like this:
第二,这只是一种 STL 实现。我的 GNU C++ 看起来像这样:
bool
empty() const
{ return begin() == end(); }
This will eventually result in a pointer comparison, while using size() would result in a subtraction (in this implementation).
这最终将导致指针比较,而使用 size() 将导致减法(在此实现中)。
3rd, it's not very likely to incur the overhead of an extra function call, since the empty()
-function is probably inlined (in both of the implementations).
第三,它不太可能产生额外函数调用的开销,因为empty()
-function 可能是内联的(在两种实现中)。
回答by paxos1977
empty() has O(1) implementations for ALL container classes. size() can only provide O(n) implementations for some containers; this is why empty() is preferred.
empty() 对所有容器类都有 O(1) 实现。size() 只能为某些容器提供 O(n) 的实现;这就是为什么 empty() 是首选。
回答by Alex
In addition to the reasons given above, it's also arguably clearer than foo.size() == 0 and/or !foo.size()
除了上面给出的原因,它也可以说比 foo.size() == 0 和/或 !foo.size() 更清晰
回答by Jakkula Vamsi
Prefer to use use empty() than size() because, each container might implement empty() implementation in a different way to get the constant time operation.
更喜欢使用 use empty() 而不是 size() 因为,每个容器可能以不同的方式实现 empty() 实现以获得恒定时间操作。
example:
例子:
vector implements as : bool empty() const { // test if sequence is empty return (size() == 0); }
vector 实现为: bool empty() const { // 测试序列是否为空 return (size() == 0); }
list implements as :
列表实现为:
bool empty() const
{ // test if sequence is empty
return (_Mysize == 0);
}
回答by Ash
Besides the readability point, which is very valid, what you experienced is simply the artifacts of one particular implementation, not the only possible one.
除了非常有效的可读性点之外,您所经历的只是一种特定实现的工件,而不是唯一可能的工件。
That is, there is no reason or requirement that empty() be implemented in terms of size() in both the vector and list case, or in deed any other container. If there are better performing alternatives, they should be used, unless the author(s) of the library are incompetent, or more reasonably, lazy.
也就是说,在 vector 和 list 的情况下,或者实际上任何其他容器中,都没有理由或要求在 size() 方面实现 empty() 。如果有性能更好的替代方案,则应使用它们,除非库的作者无能,或更合理地,懒惰。
As for the list and the O(1)-ness of size(), or the lack thereof, you should take into account that list may implement either size() as O(1) or splice(), but not both (thinking about the reason is an interesting exercise.) So in your case, the library you inspected may have implemented size() as O(1) (in which case splice() would be O(n)) and therefore could implement empty() in terms of size() without sacrificing performance, otherwise, that would be a really bad library.
至于列表和 size() 的 O(1) 度,或缺少它,您应该考虑到该列表可能将 size() 实现为 O(1) 或 splice(),但不能同时实现(思考关于原因是一个有趣的练习。)所以在您的情况下,您检查的库可能已将 size() 实现为 O(1) (在这种情况下 splice() 将是 O(n)),因此可以实现 empty()在不牺牲性能的情况下使用 size() ,否则,这将是一个非常糟糕的库。