C++ std::equal——不测试两个大小相等的范围的理由是什么?

发布于 2024-08-25 17:57:29 字数 828 浏览 3 评论 0原文

我刚刚编写了一些代码来测试 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

刘备忘录 2024-09-01 17:57:29

观察:为什么 std::equal 不首先检查两个容器是否具有相同的 size() ?有正当理由吗?

如何?您不将容器传递给函数,而是传入迭代器。函数无法知道第二个容器的大小。它所能做的就是假设用户确实传入了两个有效的容器范围(即第二个范围被正确指定为半开区间 [lst2.begin(), lst2 .begin() - lst1.begin() + lst1.end()[) 并采取相应行动。

Observation: why is it the std::equal does not first check if the 2 containers have the same size() ? Was there a legitimate reason?

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.

人海汹涌 2024-09-01 17:57:29

您始终可以编写自己的 equal 版本,它可以有效地实现您想要的功能:

template <class InputIterator1, class InputIterator2>
bool equalx(InputIterator1 first1, InputIterator1 last1,
            InputIterator2 first2, InputIterator2 last2)
{
  while ((first1 != last1) && (first2 != last2))
  {
    if (*first1 != *first2)   // or: if (!pred(*first1,*first2)), for pred version
      return false;
    ++first1; ++first2;
  }
  return (first1 == last1) && (first2 == last2);
}

为了确保两个范围具有相同数量的元素,签名必须包含第二个范围的结尾。

You can always write your own version of equal that does effectively what you want:

template <class InputIterator1, class InputIterator2>
bool equalx(InputIterator1 first1, InputIterator1 last1,
            InputIterator2 first2, InputIterator2 last2)
{
  while ((first1 != last1) && (first2 != last2))
  {
    if (*first1 != *first2)   // or: if (!pred(*first1,*first2)), for pred version
      return false;
    ++first1; ++first2;
  }
  return (first1 == last1) && (first2 == last2);
}

In order to make sure both ranges have the same number of elements, the signature must include an end to the second range.

沉溺在你眼里的海 2024-09-01 17:57:29

因为检查大小可能是一个 O(n) 操作。

Because checking the size may be an O(n) operation.

羞稚 2024-09-01 17:57:29

它给了你正确的答案 - 你告诉它检查两个容器在 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() to lst1.end(). You're still comparing two empty lists as far as equal() is concerned. If you change the code to compare from lst2.begin() to lst2.end(), you'll get what you expected.

寻找我们的幸福 2024-09-01 17:57:29

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文