如果不使用“高级”功能,是否可以增加迭代器的多个位置?

时间:2018-10-26 06:12:28

标签: c++ c++11 iterator listiterator

我知道我们可以使用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;
}

您可以运行上面的代码here

2 个答案:

答案 0 :(得分:29)

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

std::list的迭代器是BidirectionalIterator,它不支持operator +=。 (std::vectorstd::array的迭代器是RandomAccessIterator。)

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

答案 1 :(得分:15)

您不能将此迭代器与+= 2一起使用,因为通常情况下,将std::list<>迭代器递增任意值是相对 invalid 的操作。未为您的迭代器类型定义+=,专门用于防止您不小心/不知不觉地在代码中使用此低效操作。相反,如果您确实想这样做,则应该使用std::advance,这是一个“红色标志”函数,旨在强调您可能在做效率低下的事情。 std::advance主要用于代码草绘或不太可能执行的后备代码。您不应在生产代码中随意使用std::advance。如果您突然发现自己依赖std::advance,则意味着您可能需要重新设计数据结构。基本上,std::advance就像演员一样-除非有非常非常好的理由使用它,否则请避免使用它。

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

it = std::next(it, 2);

此功能比std::advance易于使用。默认情况下,此函数旨在使迭代器前进1步,但是您可以指定第二个参数将其进一步移动。同样,当第二个参数的值不是恒定的并且可能很大时,应将其视为“红色标志”函数。常数2肯定在可接受的范围内。