我可以通过添加一个数字来增加迭代器吗?

时间:2009-06-23 14:55:48

标签: c++ iterator

我可以使用迭代器进行正常计算,即只需通过添加数字来增加它吗?

例如,如果我想删除元素vec[3],我可以这样做:

std::vector<int> vec;
for(int i = 0; i < 5; ++i){
      vec.push_back(i);
}
vec.erase(vec.begin() + 3); // removes vec[3] element

它适用于我(g ++),但我不确定它是否保证能够正常工作。

4 个答案:

答案 0 :(得分:46)

如果迭代器是一个随机访问迭代器,它的向量迭代器是(参见reference)。 STL函数std::advance可用于推进泛型迭代器,但由于它不返回迭代器,因此我倾向于使用+,因为它看起来更干净。

C ++ 11 note

现在有std::nextstd::prev,其中返回迭代器,所以如果你在模板领域工作,你可以使用它们来推进通用迭代器有干净的代码。

答案 1 :(得分:2)

它适用于随机访问迭代器。一般来说,您可能希望查看更为通用的std::advance。请务必了解使用此功能模板的性能影响。

答案 2 :(得分:0)

一个微妙的地方是operator+Distance;即有符号整数。如果将迭代器增加无符号数,则可能会失去精度,并会感到意外。例如在64位系统上,

std::size_t n = (1 << 64) - 2;
std::vector<double> vec(1 << 64);
std::vector<double> slice(vec.begin() + n, vec.end());

导致未定义的行为。使用g++clang,您可以要求编译器通过警告标志-Wsign-conversion来警告您这种不受欢迎的转换,该警告标志不属于规范的-Wall或{{1 }}。

一种解决方法是直接在指针上工作

-Wextra

这不漂亮,但正确。在某些情况下,您需要手动构造迭代器,例如

std::vector<double> slice(vec.data() + n, vec.data() + vec.size());

答案 3 :(得分:0)

只有使用随机访问迭代器(例如 std::vector 和 std::deque 中的迭代器)才能进行数字运算。

    std::vector<int>list={1,2,3,4,5,6,7,8};
    auto last_v=*(list.end()-1);
    auto third_last_v=*(list.end()-3);
    std::cout<<"Last & 3rd last entry for vector:"<<last_v<<","<<third_last_v<<std::endl;

将输出 8 和 6,但是对于具有双向迭代器的 std::map、std::multimap、std::set、std::multiset

    std::map<int,std::string> map_={{1,"one"},{2,"two"},{3,"three"}};
    auto last_mp=*(map_.end()-1);
    auto third_last_mp=*(map_.end()-3);
    std::cout<<"Last & 3rd last entry for map:("<<last_mp.first<<","<<last_mp.second<<") and ("<<third_last_mp.first<<","<<third_last_mp.second<<")"<<std::endl;

会导致 error: no match for ‘operator-’ (operand types are ‘std::map, int>::iterator {aka std::_Rb_tree_iterator, int> >}’ and ‘int’)

对于双向迭代器 std::next()、std::prev 或 std::advance() 有效

    std::map<int,std::string> map_={{1,"one"},{2,"two"},{3,"three"}};
    auto last_mp=*std::prev(map_.end(),1);
    auto third_last_mp=*std::prev(map_.end(),3);
    std::cout<<"Last & 3rd last entry for map:("<<last_mp.first<<","<<last_mp.second<<") and ("<<third_last_mp.first<<","<<third_last_mp.second<<")"<<std::endl;

将输出 (3,three) 和 (1,one)。同样,std::unordered_map 有一个前向迭代器,所以这里使用 std::next() 是有意义的。