I have following code to randomize the elements in a Random Access Iterator (vector<int>::iterator
) -
#include <vector>
#include <list>
#include <iterator>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
using namespace std;
template<class RandomAccesIterator>
void randomize(RandomAccesIterator iterBegin, RandomAccesIterator iterEnd)
{
while (iterBegin != iterEnd)
{
int rand1 = rand();
auto iterdiff = iterEnd - iterBegin;
auto secondarg = iterBegin + rand1 % (iterdiff);
iter_swap(iterBegin, secondarg);
++iterBegin;
}
}
And following is the main() function:
int main()
{
//container used as to apply algorithm to.
list<int> List = {34,77,16,2,35,76,18,2,56};
//randomize example.
cout << "calling randomize on sorted vector: " << endl;
List.sort();
vector<int> temp(List.begin(), List.end());
cout << "before randomize: " << endl;
for (vector<int>::iterator it = temp.begin(); it != temp.end(); it++)
{
cout << *it << " ";
}
cout << endl;
randomize(temp.begin(),temp.end());
cout << "after randomize: " << endl;
for (vector<int>::iterator it = temp.begin(); it != temp.end(); it++)
{
cout << *it << " ";
}
cout << endl<<endl;
return 0;
}
In the randomize template function, how is the difference between iterators calculated (iterEnd - iterBegin)?
I tried a couple of things in the immediate window, and it looks like iterEnd - iterBegin is calculated like so (the vector has 9 elements in it, and the below calculation gives 9). I tried with various number of elements in the vector<int>
, and the answer was correct each time. The computation is for the first time we encounter iterEnd - iterBegin in the while loop (that is, for 9 elements in the vector):
In the immediate window -
1.
iterEnd
{-33686019}
[ptr]: 0x0080f9dc {-33686019}
[Raw View]: {...}
2.
iterBegin
{2}
[ptr]: 0x0080f9b8 {2}
[Raw View]: {...}
3.
0x0080f9dc-0x0080f9b8 //iterEnd - iterBegin gives 36.
36
4.
36/4 //Dividing 36 by 4, since an integer is 4 bytes (we are iterating over a vector of integers).
9
I also tried with 8 elements in the vector<int>
, and the same type of calculation resulted in 8 elements in step 4. above.
I have a couple of questions here:
Please see: I am using the following compiler: Microsoft Visual Studio Enterprise 2019 (Version 16.2.1). The operating system platform is 64 bit, x64-based processor. I am building on Debug x86 environment. The Windows edition is Windows 10 Pro
Your steps are correct, but only because:
int
happens to be 4 bytes long on your systemstd::vector<int>::iterator
happens to trivally wrap a raw pointer (int*
) on your systemInstead of hard-coding the value 4, you can use sizeof(int)
to evaluate the correct number of bytes on any system you compile your code on.
std::size_t numElements = (0x0080f9dc - 0x0080f9b8) / sizeof(int); // Better
As for your second question, the 36
you are calculating is not a unitless decimal value. The raw integer value of a raw pointer (remember: std::vector<int>::iterator
trivially wraps an int*
so it has the same size) uses bytes as their implicit unit, so you are actually dividing bytes by bytes in your steps.
Finally, I suggest avoiding this sort of pointer arithmetic (rationale). The standard already provides a function to calculate exactly this, std::distance
, and it will work correctly across all standard iterators and on any system you compile your code on.
std::size_t numElements = std::distance(iterBegin, iterEnd); // Best