C++ std::equal——不测试两个大小相等的范围的理由是什么?
我刚刚编写了一些代码来测试 std::equal 的行为,然后感到惊讶:
int main()
{
try
{
std::list<int> lst1;
std::list<int> lst2;
if(!std::equal(lst1.begin(), lst1.end(), lst2.begin()))
throw std::logic_error("Error: 2 empty lists should always be equal");
lst2.push_back(5);
if(std::equal(lst1.begin(), lst1.end(), lst2.begin()))
throw std::logic_error("Error: comparing 2 lists where one is not empty should not be equal");
}
catch(std::exception& e)
{
std::cerr << e.what();
}
}
输出(令我惊讶):
Error: comparing 2 lists where one is not empty should not be equal
观察:为什么它是 std::equal 不会首先检查两个容器是否具有相同的 size()
?有正当理由吗?
I just wrote some code to test the behavior of std::equal, and came away surprised:
int main()
{
try
{
std::list<int> lst1;
std::list<int> lst2;
if(!std::equal(lst1.begin(), lst1.end(), lst2.begin()))
throw std::logic_error("Error: 2 empty lists should always be equal");
lst2.push_back(5);
if(std::equal(lst1.begin(), lst1.end(), lst2.begin()))
throw std::logic_error("Error: comparing 2 lists where one is not empty should not be equal");
}
catch(std::exception& e)
{
std::cerr << e.what();
}
}
The output (a surprise to me):
Error: comparing 2 lists where one is not empty should not be equal
Observation: why is it the std::equal does not first check if the 2 containers have the same size()
? Was there a legitimate reason?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如何?您不将容器传递给函数,而是传入迭代器。函数无法知道第二个容器的大小。它所能做的就是假设用户确实传入了两个有效的容器范围(即第二个范围被正确指定为半开区间 [
lst2.begin()
,lst2 .begin()
-lst1.begin()
+lst1.end()
[) 并采取相应行动。How? You do do not pass containers to the function, you pass in iterators. The function has no way of knowing the size of the second container. All it can do is assume bona fide that the user passed in two valid container ranges (i.e. that the second range is correctly specified as the half-open interval [
lst2.begin()
,lst2.begin()
-lst1.begin()
+lst1.end()
[) and act accordingly.您始终可以编写自己的 equal 版本,它可以有效地实现您想要的功能:
为了确保两个范围具有相同数量的元素,签名必须包含第二个范围的结尾。
You can always write your own version of equal that does effectively what you want:
In order to make sure both ranges have the same number of elements, the signature must include an end to the second range.
因为检查大小可能是一个
O(n)
操作。Because checking the size may be an
O(n)
operation.它给了你正确的答案 - 你告诉它检查两个容器在
lst1.begin()
到lst1.end()
范围内是否相等。就equal()
而言,您仍在比较两个空列表。如果您将代码从lst2.begin()
更改为lst2.end()
进行比较,您将得到您所期望的结果。It's giving you the right answer - you told it to check if the two containers were equal in the range
lst1.begin()
tolst1.end()
. You're still comparing two empty lists as far asequal()
is concerned. If you change the code to compare fromlst2.begin()
tolst2.end()
, you'll get what you expected.C++14 添加了一个四参数重载,就像 R Samuel Klatchko 的答案中的重载一样。至少我检查的两个 STL 实现(libc++ 和 MSVC)为随机访问迭代器实现了明显的距离检查预先优化。
C++14 added a four-argument overload much like the one in R Samuel Klatchko's answer. And at least the two STL implementations I checked (libc++ and MSVC) implement the obvious distance-check-up-front optimization for random access iterators.