为什么 std::list 迭代器没有运算符+

Why no operator+ for std::list iterators?

本文关键字:运算符 迭代器 std list 为什么      更新时间:2023-10-16

我正要写这样的代码:

std::list<whatevertype> mylist;
// ...
std::list<whatevertype>::iterator it;
for(it = mylist.begin(); it != mylist.end(); ++it) {
    // ...
    if(some condition)
        mylist.erase(it);
}

但我意识到,这段代码是错误的:mylist.erase(x)将使迭代器it无效,因此++it可能会失败。

所以我尝试将其更改为

std::list<whatevertype>::iterator it;
std::list<whatevertype>::iterator nextit;
for(it = mylist.begin(); it != mylist.end(); it = nextit) {
    // ...
    nextit = it + 1;
    if(some condition)
        mylist.erase(it);
}

但是,令我惊讶的是,这失败了:显然operator+没有为std::list迭代器定义。

从那以后,我发现了另一个问题,并了解到删除迭代器"从下面出来"的标准习语更像

for(it = mylist.begin(); it != mylist.end(); ) {
    if(some condition)
          it = mylist.erase(it);
    else  ++it;
}

我相信我也可以侥幸逃脱

for(it = mylist.begin(); it != mylist.end(); ) {
    // ...
    std::list<whatevertype>::iterator previt = it;
    ++it;
    if(some condition)
        mylist.erase(previt);
}

但我的问题是,是否有理由没有为这些迭代器定义operator+

他们对 std 迭代器和集合的一个规则是使昂贵的东西变得冗长。

在列表迭代器上,it+50需要 O(50( 时间。 在向量迭代器上,it+50需要 O(1( 时间。 因此,他们在向量迭代器(和其他随机访问迭代器(上实现了+,但没有在列表迭代器(和其他较弱的迭代器(上实现。

std::nextstd::advancestd::prev可以更轻松地解决您的问题:

auto previt = std::prev(it);

auto nextit = std::next(it);

这些也需要计数,但由于它们是显式函数调用,因此决定它们昂贵是可以接受的。

除此之外,您还可以搜索std::nextstd::prev的调用,并获得迭代器操作; +严重超载,很难找到昂贵的电话。

请注意,std::basic_string不遵循与其他std容器相同的约定。

并不是

所有迭代器都缺少+std::list迭代器缺少它。

这是因为列表迭代器在随机访问时效率极低。因此,使随机访问变得容易是一个坏主意。

您可以使用std::advance .它使你更明显地在列表中移动,一次一个元素。

std::list 使用仅定义递增和递减的双向迭代器。由于 std::list 是一个链表,迭代器的实现一次只能移动一个节点。

该界面旨在确保您知道移动多个元素不是像其他迭代器(如从 std::vector 返回的 RandomAccessIterator(那样的简单操作。

有关不同迭代器类型的定义,请参阅 http://en.cppreference.com/w/cpp/concept/Iterator。