Мне было интересно, есть ли встроенный способ в C ++ для сравнения порядка двух двунаправленных итераторов. Например, у меня есть функция Sum для вычисления суммы между двумя итераторами в одном и том же списке:
double Sum(std::list::const_iterator Start, std::list::const_iterator End){
double sum=0;
for (Start;Start!=End;Start++)
sum+=*Start;
return sum;
}
Затем:
Sum(my_list.begin(),my_list.end());
хорошо, но Sum(my_list.end(),my_list.begin());
вызовет ошибку во время выполнения.
Я думал положитьif (Start>End) return 0;
чтобы предотвратить ошибку. Но, похоже, я не могу сравнить итераторы, как это.
Вы должны прочитать Введение в STL который объясняет различные уточнения концепции итератора.
Только RandomAccessIterators поддержка сравнения с <
потому что это не эффективная операция для не-RandomAccessIterators.
Единственный способ сказать, если BidirectionalIterator i
меньше, чем другой, j
, увеличивая i
один шаг за раз и посмотреть, если вы когда-нибудь достигнете j
, но этого никогда не произойдет, если j
недоступен из i
и является ошибкой, если i
не увеличивается, например потому что это последний итератор для диапазона.
В качестве альтернативы, вы можете уменьшить i
и посмотрим, достигнете ли вы j
в каком случае вы знаете j
меньше чем i
, но это не сработает, если i
является начальным итератором, потому что вы не можете выполнять итерацию до начала диапазона.
Таким образом, в общем, нет никакого способа узнать, приходит ли один не-RandomAccessIterator до или после другого, потому что вы даже не можете знать, начинать ли итерацию вперед или назад, чтобы достичь другого, и вы не будете знать, когда это безопасно продолжать или когда вы достигнете конца допустимого диапазона.
Таким образом, по соглашению вы всегда передаете итераторы в одном и том же порядке, так что начальный итератор идет первым, а последний итератор — вторым, а конечный итератор может быть достигнут путем увеличения нуля начального итератора или больше раз.
Затем:
Sum(my_list.begin(),my_list.end());
хорошо, ноSum(my_list.end(),my_list.begin());
вызовет ошибку во время выполнения.
Тогда не делай этого!
Ответственность за правильный вызов функции лежит на вызывающей стороне, и почему вызывающая сторона не знает, какой итератор является началом, а какой — концом?
когда вы вызываете Sum (my_list.begin (), my_list.end ()), my_list.begin () будет указывать на первый элемент в списке
double Sum(std::list::const_iterator& Start, std::list::const_iterator& End)
{
double sum=0;
if (Start;Start!=End;Start++)
sum+=*Start;
return sum;
}
SameWay, когда вы звоните Сумма (my_list.end (), my_list.begin ()),my_list.end () будет указывать на последний элемент в списке.
Сделайте ниже изменения, это будет работать,
double Sum(std::list<int>::const_iterator Start, std::list<int>::const_iterator End)
{
double sum=0;
for (Start;Start!=End;Start)
sum+=*(--Start);
return sum;
}