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

Why use std::next instead of adding an integer to the pointer?

本文关键字:指针 整数 添加 std next 为什么      更新时间:2023-10-16

我有一个快速问题。我无法计算出使用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会发出某种警告或其他什么。

任何启示都将不胜感激。

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

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

编辑:

正如Matt在评论中所说,迭代器不仅仅有一个花哨的名称和模板包装器。有些数据结构(容器)不位于连续的内存段(例如mapset)中,它们需要使用更多的逻辑来计算内存中的确切位置。迭代程序也封装了这一点,它们提供了算法和容器之间的抽象级别。

因此,总结以上几点,使用标准习语有助于编写更健壮的代码,即支持不同类型的容器(不关心它们的内存布局),同时由于编译器非常智能,尽可能保持效率。

std::next适用于所有迭代器类型。如果你知道你在处理一个数组,那么添加值就可以了。然而,如果您正在编写一个通用函数,希望在不同类型的迭代器上工作,这就带来了问题。

iter + 5

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

std::next(iter, 5)

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

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