为什么使用std :: next而不是向指针添加整数?

Kon*_*app 10 c++ pointers c++11

我只是有一个简短的问题.我无法弄清楚使用std::next而不仅仅是向指针添加所需数量的进步的好处.一个简单的例子:

 int main()
 {
     int arr [] = {1, 2, 3, 4, 5};
     cout << *(arr + 2) << ", ";    //example 1
     cout << *std::next(arr, 2) << endl;    //example 2
     return 0;
 }
Run Code Online (Sandbox Code Playgroud)

输出: 3, 3

从逻辑上讲,示例1应该更快,因为没有调用函数等.此外,在我运行此代码的实例中,如果我添加了一个会导致指针超出范围的数字(例如7),编译器会在示例1中抛出一个错误,但很高兴继续在示例2中给我一个内存地址.这与我最初的想法相矛盾:std::next如果指针超出界限,会发出某种警告或某些事情.

任何启蒙都会受到赞赏.

luk*_*k32 12

因为std::next它不仅适用于原始指针,而且适用于所有迭代器,因此它更通用.

你的假设也是假的.当使用合理的优化级别时,这两种方法很可能会导致相同的程序集.同样,c ++旨在使这种优化更容易.在您的示例中,底层迭代器类型显然是一个原始指针,并且推断函数调用可以内联是非常简单的.

编辑:

正如Matt在他的评论中所说,迭代器不仅仅是一个奇特的名字和一个模板包装器.有些数据结构(容器)不存在于连续的内存段(例如a mapset)中,它们需要使用更多逻辑,以确定内存中的确切位置.迭代器也包含它,它们在算法和容器之间提供了一定程度的抽象.

因此,总结以上几点,使用标准习语有助于编写更强大的代码,即支持不同类型的容器(不关心其内存布局),同时由于相当聪明的编译器而在可能的情况下保持效率.

  • 特别是,迭代器不支持随机访问,因此不是带有整数的"operator +". (4认同)
  • @KonradKapp在任何情况下都不能保证在越过数组时遇到错误.它调用未定义的行为,因此它可能依赖于优化标志,系统,编译器或程序员的创造力. (2认同)
  • @KonradKapp顺便说一下,我恳请你阅读一下``array`](http://en.cppreference.com/w/cpp/container/array)方法`at`和`operator []`.它们与您谈论的内容完全不同. (2认同)

Sil*_*olo 11

std::next适用于所有迭代器类型.如果您知道自己正在处理数组,那么添加该值就可以了.但是,如果您正在编写要在不同类型的迭代器上工作的泛型函数,则会产生问题.

iter + 5
Run Code Online (Sandbox Code Playgroud)

该操作仅为随机访问迭代器定义.

std::next(iter, 5)
Run Code Online (Sandbox Code Playgroud)

但是,该操作是为前向迭代器定义的,前向迭代器是一个更广泛的迭代器类别.简而言之,std::next使您的代码更加通用化.

cplusplus.com有各种迭代器类型支持的运算符的完整列表,可在此处获得.如该页面上的图表所示,所有随机访问迭代器也都是前向的,但几乎并非所有前向迭代器都是随机访问.链接列表之类的东西只适用于std::next

  • 只是添加一点,`std :: next`不仅仅是"apply` ++`5次'to iter`"的一个实现,但是足够聪明,可以用随机访问迭代器做更有效的事情,并使用前向迭代器的"慢"增量增加5倍(不能只跳跃5个位置). (5认同)