[c++] Почему стандартные итераторы диапазона [begin, end] вместо [begin, end]?


Answers

Почему стандарт определяет end() как один за концом, а не на самом конце?

Потому как:

  1. Это позволяет избежать специальной обработки для пустых диапазонов. Для пустых диапазонов begin() равен end() &
  2. Это делает конечный критерий простым для циклов, которые перебирают элементы: петли просто продолжаются до тех пор, пока end() не будет достигнут.
Question

Почему стандарт определяет end() как один за концом, а не на самом конце?




Когда end() указывает один за концом, легко итерации коллекции с циклом for:

for (iterator it = collection.begin(); it != collection.end(); it++)
{
    DoStuff(*it);
}

Когда end() указывает на последний элемент, цикл будет более сложным:

iterator it = collection.begin();
while (!collection.empty())
{
    DoStuff(*it);

    if (it == collection.end())
        break;

    it++;
}



Потому что тогда

size() == end() - begin()   // For iterators for whom subtraction is valid

и вам не придется делать неудобные вещи, как

// Never mind that this is INVALID for input iterators...
bool empty() { return begin() == end() + 1; }

и вы не будете случайно писать ошибочный код, как

bool empty() { return begin() == end() - 1; }    // a typo from the first version
                                                 // of this post
                                                 // (see, it really is confusing)

bool empty() { return end() - begin() == -1; }   // Signed/unsigned mismatch
// Plus the fact that subtracting is also invalid for many iterators

Кроме того: что бы find() return, если end() указал на действительный элемент?
Вы действительно хотите, чтобы другой член вызывал invalid() который возвращает недопустимый итератор ?!
Два итератора уже достаточно болезненны ...

О, посмотри this статью .

Также:

Если end был до последнего элемента, как бы вы insert() в истинный конец ?!




Related