Home » C++ » How to use an iterator?

# How to use an iterator?

Questions:

I’m trying to calculate the distance between two points. The two points I stored in a vector in C++: (0,0) and (1,1).

I’m supposed to get results as

``````0
1.4
1.4
0
``````

But the actual result that I got is

``````0
1
-1
0
``````

I think there’s something wrong with the way I use iterator in vector.
How can I fix this problem?

I posted the code below.

``````typedef struct point {
float x;
float y;
} point;

float distance(point *p1, point *p2)
{
return sqrt((p1->x - p2->x)*(p1->x - p2->x) +
(p1->y - p2->y)*(p1->y - p2->y));
}

int main()
{
vector <point> po;
point p1; p1.x = 0; p1.y = 0;
point p2; p2.x = 1; p2.y = 1;
po.push_back(p1);
po.push_back(p2);

vector <point>::iterator ii;
vector <point>::iterator jj;
for (ii = po.begin(); ii != po.end(); ii++)
{
for (jj = po.begin(); jj != po.end(); jj++)
{
cout << distance(ii,jj) << " ";
}
}
return 0;
}
``````

That your code compiles at all is probably because you have a `using namespace std` somewhere. (Otherwise `vector` would have to be `std::vector`.) That’s something I would advise against and you have just provided a good case why:
By accident, your call picks up `std::distance()`, which takes two iterators and calculates the distance between them. Remove the using directive and prefix all standard library types with `std::` and the compiler will tell you that you tried to pass a `vector <point>::iterator` where a `point*` was required.

To get a pointer to an object an iterator points to, you’d have to dereference the iterator – which gives a reference to the object – and take the address of the result: `&*ii`.
(Note that a pointer would perfectly fulfill all requirements for a `std::vector` iterator and some earlier implementations of the standard library indeed used pointers for that, which allowed you to treat `std::vector` iterators as pointers. But modern implementations use a special iterator class for that. I suppose the reason is that using a class allows overloading functions for pointers and iterators. Also, using pointers as `std::vector` iterators encourages mixing pointers and iterators, which will prevent the code to compile when you change your container.)

But rather than doing this, I suggest you change your function so that it takes references instead (see this answer for why that’s a good idea anyway.) :

``````float distance(const point& p1, const point& p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}
``````

Note that the points are taken by `const` references. This indicates to the caller that the function won’t change the points it is passed.

Then you can call it like this: `distance(*ii,*jj)`.

On a side note, this

``````typedef struct point {
float x;
float y;
} point;
``````

is a C-ism unnecessary in C++. Just spell it

``````struct point {
float x;
float y;
};
``````

That would make problems if this `struct` definition ever was to parse from a C compiler (the code would have to refer to `struct point` then, not simply `point`), but I guess `std::vector` and the like would be far more of a challenge to a C compiler anyway.

Questions:

By coincidence, you’re actually using a built-in STL function “distance”, which calculates the distance between iterators, instead of calling your own distance function. You need to “dereference” your iterators to get the contained object.

``````cout << distance(&(*ii), &(*jj)) << " ";
``````

As you can see from the syntax above, an “iterator” is quite a lot like a generalized “pointer”. The iterator cannot be used as “your” object type directly. In fact iterators are so similar to pointers that many standard algorithms that operate on iterators work fine on pointers as well.

As Sbi noted: your distance function takes pointers. It would be better rewritten as taking const references instead, which would make the function more “canonical” c++, and make the iterator dereference syntax less painful.

``````float distance(const point& i_p1, const point& i_p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}

cout << distance(*ii, *jj) << " ";
``````

Questions:

You might do a couple of things:

1. Make the `distance()` function take references to `point` objects. This is really just to make things more readable when calling the `distance()` function:

``````float distance(point const& p1, point const& p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}
``````
2. Dereference your iterators when calling `distance()`so you’re passing the `point` objects:

``````distance( *ii, *jj)
``````

If you don’t change the interface of the `distance()` function, you might have to call it using something like the following to get appropriate pointers:

``````distance( &*ii, &*jj)
``````