SRL Archive - General

Iterators in C++


Sin

2013-05-06 20:36:36

Can someone give me a crash course on them? I just learned about vectors, and iterators are sorta confusing me :/
@Brandon

Brandon

2013-05-06 21:47:36

From: Sin
Can someone give me a crash course on them? I just learned about vectors, and iterators are sorta confusing me :/
@Brandon



Iterators? They work the same way as pointers. Think of them the same as in Java.

In the iterator world, begin = 0 Container[0]. end = Container.size() - 1.



vector<int> Array = {10, 11, 9};

//Our list now looks like:

10, 11, 9.


for (size_t I = 0; I < Array.size(); ++I)
{
cout<<Array[I]; //will print 10, 11, 9.
}

for (size_t I = Array.size(); I > 0; --I)
{
cout<<Array[I]; //will then print 9, 11, 10.
}


//Similarly, the following uses iterators to do the same:

for (vector<int>::iterator I = Array.begin(); I != Array.end(); ++I)
{
//Prints 10, 11, 9.
cout<<*I; //I said an Iterator was like a pointer. To get the value of the iterator, we do *IteratorVariable. The * operator de-references a pointer to get the value the pointer points at.
}

//vector<int>::iterator I. This tells the compiler to create an iterator that will loop through a vector of integers.
//I = Arrays.begin(); This tells the compiler that the iterator will start at the beginning of the array.
//I != Arrays.end(); The loop will continue as long as the Iterator does not reach the end of the array.
//++I. Increment the iterator. When the Iterator reaches Arrays.end(), it will break out of the loop.



for (vector<int>::iterator it = Arrays.end(); I != Arrays.begin(); ++I) //Loop backwards from the end to the beginning of the array.
{
cout<<*it; //prints 9, 11, 10.
}


//Now there are other cases where dereferencing requires the pointed-by operator aka -> OR *. ;
//Example:


pair<int, string> Dictionary;
Dictionary.insert(1, "Sin");
Dictionary.insert(2, "Is");
Dictionary.insert(3, "Learning");
Dictionary.insert(4, "C++");


//To iterate this, we do pair<int, string>::iterator it = ....
//That tells the compiler create an iterator for generic/template pair class that has the parameters <int, string>.

//Imagine the pair class to look like the following:

class pair<T>
{
T first;
T second;
};


for (pair<int, string>::iterator it = Dictionary.begin(); it != Dictionary.end(); ++it) //Loop through from beginning to end..
{
cout<<"First Value at :"<< it->first <<" Is :"<< it->second;
}

//The above forloop will thus print:

"First Value at: 1 Is: Sin"
"First Value at: 2 Is: Is"
"First Value at: 3 Is: Learning"
"First Value at: 4 Is: C++"

//The -> operator of the iterator calls the variable or function that is pointed to by the iterator. So in other words, that pair class contained a variable called first and another called second.
//To access these variables, we do ->first or -> second.
//Another way is to do: *it.first or *it.second. //This dereferences it and then accesses the variables first, second.


To visualize how iterators work under the hood, here's a small sample:


vector<int> SomeList = {1, 7, 4, 2, 6, 3, 5};

//With a pointer:

int* iterator_begin = &SomeList[0]; //A pointer to the beginning of the List aka index [0].
int* iterator_end = &SomeList[6]; //Our List is of size 7. Thus the last index is [6].

//prints the entire List from beginning to end. Since iterators are pointers under the hood,
//We must dereference the pointer to get the value.
for (iterator_begin; iterator_begin != iterator_end; ++iterator_begin)
{
cout<< *iterator_begin;

}

//Notice that the above iterators are of integer type. That's because we are iterating over an integer vector.
//A char iterator would give use bytes instead of the values in our list. That's how it all works under the hood.

wthomas

2013-05-06 22:06:53

Be careful, if its the same as C then i++ and ++i are not the same statement, and have slightly different effects in loop structures.

Brandon

2013-05-06 22:09:37

From: wthomas
Be careful, if its the same as C then i++ and ++i are not the same statement, and have slightly different effects in loop structures.


Not only in C, but in every language. Though, in a for loop declaration, they have the same effect because the incrementation always happens at the end of the loop. In fact, small micro-optimization: ++I in a for-loop is faster than I++ as there is no temporary made:




class Values<T>
{
public:
T Value = 0;

//++I Pre-Increment.
T operator++() //Should return T& but just for visualization, return T.
{
return (Value = Value + 1); //Increments the Value regardless..
}

//I++ Post-Increment.
T operator++ (T Value) //Should return T& but just for visualization, return T.
{
T Temporary = Value; //First store the original variable.
Value = Value + 1; //Increment the original variable.
return Temporary; //Return the stored value.
}
};

wthomas

2013-05-06 22:17:40

From: Brandon
Not only in C, but in every language. Though, in a for loop declaration, they have the same effect because the incrementation always happens at the end of the loop. In fact, small micro-optimization: ++I in a for-loop is faster than I++ as there is no temporary made


You sir are correct, just tested with java and c. There was some reason for needing one type over the other we covered a few weeks ago, using polling loops and hardware interrupts. :)

I believe its mainly come from functional programming where everything is a function so :


i=10;
a=10++;

i=10;
b=++10;
Where a is 10 and b is 11. I think that is the correct way around. :)

heron_

2013-05-06 22:38:03

From: Brandon
Not only in C, but in every language. Though, in a for loop declaration, they have the same effect because the incrementation always happens at the end of the loop. In fact, small micro-optimization: ++I in a for-loop is faster than I++ as there is no temporary made:




class Values<T>
{
public:
T Value = 0;

//++I Pre-Increment.
T operator++() //Should return T& but just for visualization, return T.
{
return (Value = Value + 1); //Increments the Value regardless..
}

//I++ Post-Increment.
T operator++ (T Value) //Should return T& but just for visualization, return T.
{
T Temporary = Value; //First store the original variable.
Value = Value + 1; //Increment the original variable.
return Temporary; //Return the stored value.
}
};


Most compilers can optimize post-increment to pre-increment too.


From: wthomas
You sir are correct, just tested with java and c. There was some reason for needing one type over the other we covered a few weeks ago, using polling loops and hardware interrupts. :)

I believe its mainly come from functional programming where everything is a function so :


i=10;
a=10++;

i=10;
b=++10;
Where a is 10 and b is 11. I think that is the correct way around. :)


That doesn't really make sense? How does functional programming have anything to do with that?

senrath

2013-05-06 22:46:09

From: wthomas
Where a is 10 and b is 11. I think that is the correct way around. :)


Yeah, you got it the right way around.

wthomas

2013-05-06 23:46:24

heron_ The only difference in using them is for functional programming. If you are using them for just iterating variables in loops then it matters not which you use. However in some cases you need to be specific. In non functional programming it makes no difference.

Richard

2013-05-07 12:05:05

From: wthomas
You sir are correct, just tested with java and c. There was some reason for needing one type over the other we covered a few weeks ago, using polling loops and hardware interrupts. :)

I believe its mainly come from functional programming where everything is a function so :


i=10;
a=10++;

i=10;
b=++10;
Where a is 10 and b is 11. I think that is the correct way around. :)


Java has post-incrementation?! I've been using it for years and never knew that…

heron_

2013-05-07 23:40:21

From: wthomas
heron_ The only difference in using them is for functional programming. If you are using them for just iterating variables in loops then it matters not which you use. However in some cases you need to be specific. In non functional programming it makes no difference.


Ok then, what about

buffer[i++] = x;

vs

buffer[++i] = x;

?

It's not "functional programming" and there's a huge difference.

tealc

2013-05-08 06:11:29

From: Carll
There are two types of iterators : Pre and post.
Pre ++i ( first increases and than use the value)
Post i++ (first uses and than increases the value)


Not necessarily iterators are just how you navigate between variables.
ie: binary trees often use left(), right() and parent()