1

I am using std::equals defined in <algorithm> to check if two vectors are equal. It crashes when second vector is empty. I could avoid crash by checking if second vector is empty, but is there a reason to not include the check in equal function itself ?

Sample code:

std::vector<int> a;
for (int i = 0; i < 3; ++i) a.emplace_back(i);

std::vector<int> b;
for (int i = 0; i < 0; ++i) b.emplace_back(i);

std::equal(a.begin(), a.end(), b.begin());
Evg
  • 25,259
  • 5
  • 41
  • 83
user10439725
  • 129
  • 7
  • 3
    You are using the wrong overload, the one you are calling requires that the last parameter refers to a container that has at least as many elements as the first container – UnholySheep Jan 08 '22 at 14:40
  • 1
    Because the iterator in b goes out of range. equal does not check the sizes of the containers just iterates (https://stackoverflow.com/questions/2457072/c-stdequal-rationale-behind-not-testing-for-the-2-ranges-having-equal-siz) – Pepijn Kramer Jan 08 '22 at 14:41
  • 1
    Just use : (a==b) it is implemented for vectors and does check the sizes of the containers too. https://en.cppreference.com/w/cpp/container/vector/operator_cmp – Pepijn Kramer Jan 08 '22 at 14:43
  • Here is an example program with a [mcve]: [https://ideone.com/q7kQ13](https://ideone.com/q7kQ13) – drescherjm Jan 08 '22 at 14:43
  • @UnholySheep I didn't find any other overload on https://www.cplusplus.com/reference/algorithm/equal/. Only other overload requires specifying comparison function. Can you point out the overload to use ? – user10439725 Jan 08 '22 at 15:44
  • @user10439725 cplusplus.com is not a good reference site, prefer using cppreference.com: https://en.cppreference.com/w/cpp/algorithm/equal – UnholySheep Jan 08 '22 at 15:51

2 Answers2

4

You call std::equal with 3 arguments, which in https://en.cppreference.com/w/cpp/algorithm/equal says:

Returns true if the range [first1, last1) is equal to the range [first2, first2 + (last1 - first1)), and false otherwise

which will cause undefined behavior in you case

Use std::equal with 4 arguments instead:

std::equal(a.begin(), a.end(), b.begin(), b.end());

which will do:

Returns true if the range [first1, last1) is equal to the range [first2, last2), and false otherwise.

which is what you want.

Or, you can just use operator ==. std::vector overloads one:

a == b;
3

The range (as the number of comparisons) of compared elements in this call

std::equal(a.begin(), a.end(), b.begin());

is specified by the first two arguments [a.begin(), a.end() ). But this range is invalid for the vector b.

Use this form of the algorithm

template<class InputIterator1, class InputIterator2>
bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2);

where ranges are specified separately for the both compared containers as

std::equal(a.begin(), a.end(), b.begin(), b.end());
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335