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

时间:2015-06-29 22:45:29

标签: 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;
 }

输出:3, 3

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

任何启蒙都会受到赞赏。

2 个答案:

答案 0 :(得分:12)

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

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

编辑:

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

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

答案 1 :(得分:10)

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

iter + 5

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

std::next(iter, 5)

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

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