Почему я не могу использовать оператор += в итераторе списка?
У меня есть итератор из std::list<std::string>
, но когда я пытаюсь продвинуть его, используя +=
, Я получаю ошибку компиляции.
Код является:
#include <list>
#include <iostream>
#include <string>
int main() {
std::list<std::string> x;
x.push_front("British");
x.push_back("character");
x.push_front("Coding is unco");
x.push_back("Society");
x.push_back("City Hole");
auto iter = x.begin();
iter += 3;
//std::advance(iter, 3);
x.erase(iter);
for (auto &e: x) {
std::cout << e << "\n";
}
}
Если я скомпилирую это с помощью clang++ -std=c++11 -o li li.cpp
, Я получил:
li.cpp:13:10: error: no viable overloaded '+='
iter += 3;
~~~~ ^ ~
1 error generated.
Почему я не могу использовать +=
с этим итератором?
3 ответа
Итератором для std::list является BidirectionalIterator, который не поддерживает operator+=
как RandomAccessIterator.
Ты можешь использовать operator++
, который поддерживается InputIterator (в том числе BidirectionalIterator
), что-то вроде
++iter;
++iter;
++iter;
Но это безобразно. Лучший способ, как вы прокомментировали, использовать вместо него std:: advance (или std:: next (начиная с C++11)), который можно использовать с InputIterator (включая BidirectionalIterator
), а также использует возможности, поддерживаемые RandomAccessIterator
,
(акцент мой)
сложность
Linear.
Однако если
InputIt
дополнительно отвечает требованиямRandomAccessIterator
, сложность постоянна.
Таким образом, вы можете просто использовать его без учета категории итератора, std::advance
сделает лучший выбор для вас. например
std::advance(iter, 3);
или же
iter = std::next(iter, 3);
Причина в том, что +=
Оператор не определен для двунаправленного итератора, который вы используете.
Для всех итераторов есть как минимум:
- Копируемый и разрушаемый, т.е.
X b(a);
а такжеb = a;
- Может быть увеличено, т.е.
++a
а такжеa++
Все остальное зависит от типа итератора, проверьте таблицу здесь:
Как видите, итератор с произвольным доступом сделает свое дело.
std::list::iterator
не является итератором произвольного доступа Невозможно "перескочить" несколько элементов в списке, вы должны перебирать список, пока не достигнете нужного элемента. Ты можешь использовать std::advance
который выведет лучший способ продвижения итератора на основе категории итератора. В случае std::list::iterator
он будет увеличивать итератор в цикле.