为什么没有operator + for std :: list iterators?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么没有operator + for std :: list iterators?相关的知识,希望对你有一定的参考价值。

我打算写这样的代码:

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迭代器定义。

我已经找到了this other question并且学会了删除“从下面”迭代器的标准习惯用法更像是

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::advance以及std::prev可以更轻松地解决您的问题:

auto previt = std::prev(it);

要么

auto nextit = std::next(it);

这些也需要计算,但因为它们是一个明确的函数调用,所以决定它们的价格昂贵是可以接受的。

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

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

另一答案

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

那是因为列表迭代器在随机访问时非常低效。因此,随意访问是一个坏主意。

你可以使用std::advance。更明显的是,您一次只能在列表中移动一个元素。

另一答案

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

该接口旨在确保您知道通过多个元素移动不是一个简单的操作,就像使用其他迭代器一样,例如从std :: vector返回的RandomAccessIterator。

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

以上是关于为什么没有operator + for std :: list iterators?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::optional operator* 没有 has_value() 的调试模式断言?

std::vector::insert 与 std::list::operator[]

如果键不存在,为啥 std::map operator[] 会创建一个对象?

std::unordered_map::operator[] - 为啥有两个签名?

如何将 std::map::operator= 与初始值设定项列表一起使用

为啥 std::rel_ops::operators 在 C++20 中会被弃用?