头文件'equal.hpp' 包含一个STL算法 equal 的两个变种。该算法测试两个序列是否包含相同的值。在(被提倡使用的)C++14 以前的版本中,stl::equal 函数带有三个迭代器以及一个可选的用作比较的谓词。前两个迭代器[first1,last1)定义了一个参数序列,第三个迭代器first2定义了第二个参数序列的开始位置。算法假设第二个序列长度与第一个一样长。
在C++14中,两个新的equal算法的变体被推荐使用。他们带有4个迭代器以及一个可选的用作比较的谓词参数。4个迭代器[first1, last1) 和 [first2, last2)明确的定义了两个序列范围。这样做使得他们在更多地情况下也适用,避免了其他未定义的行为。
原文链接:http://www.boost.org/doc/libs/1_60_0/libs/algorithm/doc/html/algorithm/CXX14.html
考虑一下如下两个序列:
auto seq1 = { 0, 1, 2 };
auto seq2 = { 0, 1, 2, 3, 4 };
// 返回true
//备注,算法假设第二个序列长度与第一个一样长。按照如下传递参数的情况看,seq2 在与seq1长度相同的范围内有相同的元素
std::equal ( seq1.begin (), seq1.end (), seq2.begin ());
//为什么未定义?因为seq1在长度与seq2长度一样长的时候,seq1部分元素是未定义的
std::equal ( seq2.begin (), seq2.end (), seq1.begin ()); // 这是未定义的行为
std::equal ( seq1.begin (), seq1.end (), seq2.begin (), seq2.end ()); // 返回false
你可能确切的说第一个例子返回true是正确的,尽管序列并不一致。在序列seq2的前N个元素确实与序列seq1中的元素一致——虽然那并不是seq2的全部元素。但是在第二个例子中,算法将会读取越过seq1结尾的元素,导致未定义的行为(程序崩溃、不正确的行为、像怀孕的猫一样不可预测)。
然而,假如两个序列完全一致,毫无疑问,他们是相等的。
官方API
equal函数返回true,假如两个序列比较后相等;比如,假如每一个在序列中的元素与另一个序列中对应的元素相同的话。其中一个版本使用std::equal_to来做比较;另一个版本通过传递谓词做比较。
template <class InputIterator1, class InputIterator2>
bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 );
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred );
例子
假设有一个容器c1 {0,1,2,3,14,15},以及容器c2 {1,2,3},如下操作:
equal ( c1.begin (), c1.end (), c2.begin (), c2.end ()) --> false
equal ( c1.begin () + 1, c1.begin () + 3, c2.begin (), c2.end ()) --> true
//空序列总是相等的
equal ( c1.end (), c1.end (), c2.end (), c2.end ()) --> true
迭代器要求
equal算法可作用于出来输出迭代器之外的所有迭代器。
时间复杂度
equal的两个变体的时间复杂度都是O(N);也就是说,他们比较序列中的所有元素仅仅一次。如果发现序列中的任何一个位置的元素与另一个序列不相等,算法将马上停止比较。
异常安全
equal的两种变体都传值或者传引用调用他们的参数,两种变体不依赖任何全局的状态。因此他们提供了很强的的异常安全保证。
注意
equal的四个迭代器版本属于C++14 标准。 当C ++14标准库的实现变得可用,应使用标准库的实现。当equal作用于两个空序列时候,不论传递的谓词是什么都返回true。