我们可以在没有'advance'功能的情况下增加多个位置的迭代器吗?

Lus*_* Li 16 c++ iterator listiterator c++11

我知道我们可以使用advance()函数来增加迭代器.我们还使用iterator++一个位置来增加迭代器.为什么我们不能使用it+=2

int main()
{
    list<int> l1{1, 2, 3, 5, 6};
    list<int> l2{2, 6, 8};
    auto it = l1.begin();
    advance(it, 2);         //works
    it++;                   //works
    // it+=2;                  //not work
    l2.splice(l2.begin(), l1, it);

    for(int a: l2) cout<<a<<" ";
    cout<<endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处运行上述代码.

son*_*yao 30

operator +=只有RandomAccessIterator支持; 请注意,它应该具有恒定的复杂性.

的迭代器std::listBidirectionalIterator,不支持operator +=.(的迭代std::vectorstd::array为RandomAccessIterator的.)

注意,当用于RandomAccessIterator复杂度是常数时,它们都可以与std :: advance一起使用; 当用于其他InputIterators(包括BidirectionalIterator)时,复杂性是线性的.这意味着使用std::advance是个好主意,因为它更通用,可以自动利用RandomAccessIterator的优势.

  • 是否'std :: advance`是一个好主意取决于您对算法的复杂性保证.使用`+ =`确保如果有人不小心用非RandomAccessIterator调用你的算法,他们将得到编译时错误,而不是一个痛苦的慢速算法.例如,如果`std :: sort`使用`std :: advance`,你可以在`std :: list`上调用它... (5认同)
  • 如果要基于IteratorCategory强制执行编译时复杂度,请使用static_assert执行此操作,而不是使用某些语法无法使用太弱的迭代器... (3认同)

AnT*_*AnT 15

您不能使用+= 2此迭代器,因为通常情况下,std::list<>通过任意值递增迭代器是一种效率相对较低的操作.+=未针对您的迭代器类型定义,以防止您在代码中不小心/不知情地使用此低效操作.相反,如果你真的想这样做你应该使用std::advance,这是一个"红旗"功能,旨在强调你可能做一些效率低下的事实.std::advance主要用于代码草绘或不太可能执行的回退代码.你不应该无偿地使用std::advance生产代码.如果您突然发现自己依赖std::advance,则意味着您可能需要重新设计数据结构.基本上,std::advance就像一个演员 - 除非你有一个非常非常好的理由使用它,否则请避开它.

或者,您可以使用 std::next

it = std::next(it, 2);
Run Code Online (Sandbox Code Playgroud)

这个功能比使用起来更容易std::advance.默认情况下,此函数用于将迭代器向前推进1步,但您可以指定第二个参数以将其移动得更远.同样,当第二个参数的值非常量且可能很大时,应将其视为"红旗"函数.常数值2绝对在可接受的范围内.

  • @WorldSEnder - `+ =`与常量时间操作相关联,因为这是STL(标准模板库)的设计方式:迭代器操作是常量时间.期.诸如`std :: advance`和`std :: next`之类的东西是由不了解原始配方优雅的修正主义者添加的便利.<g>但严重的是:那些是便利,它们被命名为功能而不是运营商,以帮助明确它们可能很昂贵. (3认同)