C ++ std :: equal - 不测试具有相同大小的2个范围的基本原理?

时间:2010-03-16 18:31:20

标签: c++ stl

我刚刚编写了一些代码来测试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首先检查2个容器是否具有相同的size()?有合理的理由吗?

5 个答案:

答案 0 :(得分:12)

  

观察:为什么std :: equal首先检查2个容器是否具有相同的大小()?有合理的理由吗?

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

答案 1 :(得分:4)

您可以随时编写自己的版本,以实现您想要的效果:

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);
}

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

它给你正确答案 - 你告诉它检查两个容器在lst1.begin()lst1.end()范围内是否相等。就equal()而言,您仍在比较两个空列表。如果您将代码更改为从lst2.begin()lst2.end()进行比较,那么您将得到预期的结果。

答案 4 :(得分:0)

C ++ 14增加了一个四参数重载,就像R Samuel Klatchko的答案中的重载一样。至少我检查的两个STL实现(libc ++和MSVC)为随机访问迭代器实现了明显的距离检查前端优化。