[英]Why no 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);
}
但是,令我惊讶的是,这失败了:显然没有为std::list
迭代器定义operator+
。
从那以后,我发现了另一个问题,并了解到删除“从下面”迭代器的标准习惯用法更像
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::next
和std::advance
和std::prev
可以更轻松地解决您的问题:
auto previt = std::prev(it);
要么
auto nextit = std::next(it);
这些也很重要,但是由于它们是显式的函数调用,因此可以确定它们是昂贵的。
除其他外,您可以搜索对std::next
和std::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 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.