📜 ⬆️ ⬇️

Interesting logic Random access iterators in STL containers

During programming courses I received a task - to write an analog std :: vector in C ++ with preservation of the function and interface, in order to make it at least twice as fast a million times more readable. In the course of execution, I was faced with the fact that Random access iterators have some very strange interesting features that I wanted to change. Who cares - welcome under cat.

Briefly about iterators

On Habré there is already a good article about iterators here
From myself I want to add only the definition from the article about iterators on Wikipedia.
Iterator - an object that abstracts a single interface access to the elements of the collection.
Create an iterator

So, create two vectors of integers:
vector<int> vector1; vector<int> vector2; 

Fill both numbers from 0 to 14:
  for ( int i = 0; i < 15; i++ ) { vector1.push_back(i); vector2.push_back(i); } 

Create iterators for each vector:
  vector<int>::iterator it1 = vector1.begin(); vector<int>::iterator it2 = vector2.begin(); 

Actually interesting features

The first thing that caught my eye was the presence of an overloaded operator "-" and the absence of an overloaded operator "+" for two iterators (the addition of an iterator with an int is provided for). Create an additional iterator for the first vector and do both:
  vector<int>::iterator temp = vector1.begin() + 3; cout << temp - it1 << endl; <s> cout << temp + it1 << endl;</s> 

In the first case, we obtain output 3, in the second, a compilation error.

Secondly, I was interested in the issue of equality of iterators. Based on the definition, the iterator must provide access to the elements of the collection. That is, if two iterators belong to different collections, cap suggests that you cannot compare them at all. But:
  if ( it1 == it2 ) { cout << "Equal" << endl; } else { cout << "Not equal" << endl; } 

At the exit, we have “Not equal”, which, given the strangeness of the very possibility of such a comparison, is very logical.
After I realized that it was possible to compare iterators of different objects, I decided to try to subtract one from the other:
  cout << it1 - it2 << endl; 

At the output we get 34. Immediately I remembered Pelevin and his "Numbers".
Brief annotation
The hero of Pelevin’s novel “Numbers” is a businessman Stepan. Even as a child, Stepa realized that he was not like everyone else. Stepa felt an inexplicable latent craving for number 7, but did not understand how to please this great number, which so many talented people worship. As a result, he realized that 7 is nothing more than 3 + 4 (which we will see later on), so he began to worship the number 34, subjugating to him all his life.
Taken from pelevin.nov.ru/stati/o-lleo2/1.html

The fact that at the output we get unpredictable int is connected with how the vectors are located in memory relative to each other. Having tried to fill both vectors with different numbers of numbers, I got a completely different result.

Well, the most interesting:
  it2 += 34; if ( it1 == it2 ) { cout << "Equal" << endl; } else { cout << "Not equal" << endl; } 

At the exit, as you already guessed "Equal". This leads to the following, disappointing from my point of view, conclusion that:
  it2 = vector2.begin() + 34; 

let us iterate the first vector, not the second.
')
findings

When creating the Random access iterator, the developers did not limit the use of the iterator only to the framework of the container for which it was created. I can understand their logic, although I personally don’t like it. Close comparison and subtraction of iterators pointing to different vectors would not be very difficult. And although, perhaps, such situations are rare, do not forget about these features.

Source: https://habr.com/ru/post/154761/


All Articles