Я просто написал некоторый код для тестирования поведения станд.:: равный, и ушел удивленный:
int main()
{
try
{
std::list lst1;
std::list 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
Наблюдение: почему это станд.:: равный сначала не проверяет, имеют ли эти 2 контейнера то же size()
? Была ли законная причина?
Наблюдение: почему std :: equal не проверяет сначала, имеют ли 2 контейнера одинаковый размер ()? Была ли на то законная причина?
Как? Вы не передаете в функцию контейнеры, вы передаете итераторы . Функция не может узнать размер второго контейнера . Все, что он может сделать, это предположить добросовестно, что пользователь передал два допустимых диапазона контейнеров (т.е. что второй диапазон правильно указан как полуоткрытый интервал [ lst2.begin ()
, lst2). begin ()
- lst1.begin ()
+ lst1.end ()
[) и действуйте соответственно.
Вы всегда можете написать свою собственную версию равного, которая эффективно делает то, что вы хотите:
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);
}
Чтобы убедиться, что оба диапазона имеют одинаковое количество элементов, подпись должна включать конец второго диапазона.
Поскольку проверка размера может быть операцией O(n)
.
Это дает вам правильный ответ - вы сказали ему проверить, равны ли два контейнера в диапазоне lst1.begin()
до lst1.end()
. Вы все еще сравниваете два пустых списка, если речь идет о equal()
. Если вы измените код для сравнения с lst2.begin()
на lst2.end()
, вы получите то, что ожидали.