std::advance和std::next有什么区别?

79

除了进阶部分,是否还有处理负数的内容?

4个回答

117

std::advance

  • 修改其参数
  • 不返回任何内容
  • 适用于输入迭代器或更好的迭代器(如果给定负距离,则适用于双向迭代器)

std::next

  • 不修改其参数
  • 返回由指定数量前进的参数的副本
  • 适用于正向迭代器或更好的迭代器(如果给定负距离,则适用于双向迭代器)

我不确定你是否知道为什么他们将在输入迭代器上使用next定义为保证工作的效果,即使它不是前向迭代器,但它仍然是UB。 - Steve Jessop
@HowardHinnant:谢谢。所以基本上,如果你正在使用InputIterator,那么你应该只使用++(或者advance,以保护自己免受涉及next的一行代码的便利性的摧残),或者编写自己的my_next,这可能与你实现的std::next完全相同,也许去掉了特征断言。我想到了同样的论点,InputIterator不应该需要operator++(int)。现在修复已经太晚了,我想。 - Steve Jessop
6
如果我有一台时间机器,我会取消InputIterator的复制构造函数,并将其变为只移动的。我认为这将使它们更加安全和易于理解。 - Howard Hinnant
2
std::next的额外约束已被取消,详情请参考http://cplusplus.github.io/LWG/lwg-defects.html#2353。 - T.C.

21

或许最大的实际区别是 std::next() 仅在 C++11 及以上版本可用。

std::next() 默认情况下会向前移动一个,而 std::advance() 需要指定距离。

然后就是返回值:

std::next()std::advance 一样可以接受负数参数,但是在这种情况下,迭代器必须是双向迭代器。当特别想要向后移动时,使用 std::prev() 可以让代码更加易读。


2
next 不仅向前移动,它在这方面类似于 advance。鉴于存在 prev,写 next(it, -1) 可能有些奇怪,因为这是一个否定的文字。但对于正确类别的迭代器,例如写 next(it, distance(it2, it3)) 即使 it2 > it3 也是可以的。 - Steve Jessop
1
@SteveJessop:感谢您的编辑和保持可读性的重点。 - johnsyweb
@Johnsyweb std::next() 在 C++11 之后就可用了,不仅仅是在 C++11 中。 - John
谢谢@John。我写下这个答案的时候是正确的,那是九年前的事情了。 - johnsyweb

7

std::advance

函数 advance() 增加传递作为参数的迭代器的位置。因此,该函数允许迭代器向前(或向后)移动多个元素:

#include <iterator>
void advance (InputIterator& pos, Dist n)
  • 让输入迭代器pos向前(或向后)移动n个元素。
  • 对于双向迭代器和随机访问迭代器,n可以为负数以向后移动。
  • Dist是一个模板类型。通常,它必须是一个整数类型,因为会调用<,++,--,以及与0的比较等操作。
  • 注意,advance()不会检查是否越过序列的end()(因为迭代器通常不知道它们所操作的容器)。因此,调用这个函数可能会导致未定义行为,因为针对序列的结尾调用operator ++是没有定义的。

std::next(和C++11中新增的std::prev

#include <iterator>
ForwardIterator next (ForwardIterator pos)
ForwardIterator next (ForwardIterator pos, Dist n)

返回结果如下:
  • 返回向前移动1或n个位置后,正向迭代器pos的位置。
  • 对于双向和随机访问迭代器,n可以是负数,以返回先前的位置。
  • Dist是类型std :: iterator_traits :: difference_type。
  • 为内部临时对象调用advance(pos,n)。
  • 请注意,next()不检查它是否跨越序列的end()。 因此,需要调用者确保结果有效。

引用自The C++ Standard Library Second Edition


4

它们基本相同,不同的是std::next返回一个副本而std::advance修改其参数。请注意,标准要求std::next的行为类似于std::advance

24.4.4 Iterator operations [iterator.operations]

template <class InputIterator, class Distance>
void advance(InputIterator& i [remark: reference], Distance n);

2. Requires: n shall be negative only for bidirectional and random access iterators
3. Effects: Increments (or decrements for negative n) iterator reference i by n.
[...]

template <class ForwardIterator>
ForwardIterator next(ForwardIterator x, [remark: copy]
     typename std::iterator_traits<ForwardIterator>::difference_type n = 1);

6. Effects: Equivalent to advance(x, n); return x;

请注意,如果迭代器是输入迭代器,则两者都支持负值。此外,请注意,std::next要求迭代器满足ForwardIterator的条件,而std::advance仅需要一个Input Iterator(如果您不使用负距离)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接