Можем ли мы увеличить количество позиций итератора без функции «вперед»?

Я знаю, что мы можем использовать функцию advance() для увеличения итератора. Мы также используем iterator++ для увеличения итератора на одну позицию. Почему мы не можем использовать it+=2 ?

int main()
{
    list<int> l1{1, 2, 3, 5, 6};
    list<int> l2{2, 6, 8};
    auto it = l1.begin();
    advance(it, 2);         //works
    it++;                   //works
    // it+=2;                  //not work
    l2.splice(l2.begin(), l1, it);

    for(int a: l2) cout<<a<<" ";
    cout<<endl;

    return 0;
}

Вы можете запустить вышеуказанный код здесь .

Всего 2 ответа


operator += поддерживается только RandomAccessIterator ; обратите внимание, что он должен иметь постоянную сложность.

Итератором std::list является BidirectionalIterator , который не поддерживает operator += . (Итератором std::vector и std::array является RandomAccessIterator.)

Обратите внимание, что оба они могут использоваться с std :: advance , когда используется для сложности RandomAccessIterator, является постоянной; когда используется для других InputIterators (включая двунаправленныйИтератор), сложность линейна. Это означает, что использование std::advance является хорошей идеей, потому что оно более общее и может автоматически воспользоваться преимуществами RandomAccessIterator.


Вы не можете использовать += 2 с этим итератором, потому что в общем случае приращение std::list<> iterator произвольным значением является относительно неэффективной операцией. += не определен для вашего типа итератора, специально для того, чтобы вы небрежно / неосознанно использовали эту неэффективную работу в своем коде. Вместо этого, если вы действительно хотите сделать это, вы должны использовать std::advance , что является функцией «красного флага», которая призвана подчеркнуть тот факт, что вы, вероятно, делаете что-то неэффективное. std::advance в основном предназначен для создания эскизов кода или для маловероятного получения кода возврата. Вы не должны безвозмездно использовать std::advance в производственном коде. Если вы вдруг обнаружите, что полагаетесь на std::advance , это означает, что вам, вероятно, придется перепроектировать ваши структуры данных. В принципе, std::advance похож на бросок - избегайте его, если у вас нет очень очень веских оснований для его использования.

Кроме того, вы можете использовать std::next

it = std::next(it, 2);

Эта функция намного проще в использовании, чем std::advance . По умолчанию эта функция предназначена для продвижения итератора на 1 шаг вперед, но вы можете указать второй параметр, чтобы переместить его дальше. Опять же, когда значение второго параметра является непостоянным и потенциально большим, его следует рассматривать как функцию «красного флага». Постоянное значение 2 определенно находится в допустимых пределах.


Есть идеи?

10000