Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I just have a quick question. I can't figure out the benefits of using std::next over just adding the desired number of advancements to the pointer. A simple example:

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

Output: 3, 3

Logically, example 1 should be quicker, since no function is called, etc. Also, in the instance in which I ran this code, if I added a number that would cause the pointer to be out of bounds (e.g. 7), the compiler would throw an error in example 1, but would happily go ahead and give me a memory address in example 2. This contradicted what I thought at first: that std::next would give some kind of warning or something if the pointer was out of bounds.

Any enlightenment would be appreciated.

like image 760
Konrad Avatar asked Jun 29 '15 22:06

Konrad


2 Answers

std::next works with all iterator types. If you know you're dealing with an array, adding the value works fine. However, if you're writing a generic function that you want to work on different kinds of iterators, that poses a problem.

iter + 5

That operation is only defined for random access iterators.

std::next(iter, 5)

However, that operation is defined for forward iterators, which is a much broader category of iterator. In short, std::next makes your code more generalized.

cplusplus.com has a full list of the operators supported by various iterator types, available here. As the chart on that page shows, all random access iterators are also forward but not nearly all forward iterators are random access. Things like linked lists will only work with std::next

like image 28
Silvio Mayolo Avatar answered Nov 20 '22 16:11

Silvio Mayolo


Because std::next is designed not only to work on raw pointers but on all iterators, therefore it's more versatile.

Your assumption is also false. Both approaches will most likely result in the same assembly when using reasonable optimization level. Again, c++ is designed to make such optimizations easier. In your example the underlying iterator type is a raw pointer, obviously, and it is quite trivial to deduce that the function call can be inlined.

EDIT:

As Matt said in his comment, there are more to iterators than just a fancy name and a template wrapper. There are data structures (containers) which do not reside in a contiguous memory segment (e.g. a map or set) they need to use more logic, to figure out the exact placement in memory. Iterators also wrap this, they provide a level of abstraction between algorithms and container.

So summing above points, using standard idioms helps in writing more robust code, i.e. supporting different types of containers (not caring about their memory layout) while keeping efficiency where possible due to quite smart compilers.

like image 116
luk32 Avatar answered Nov 20 '22 16:11

luk32