How to use an iterator? - c++

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.

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) << " ";

You might do a couple of things:
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(const point& p1, const point& p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}
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)

Related

C++ / How does a iterator work for a Set of class object?

I've been teaching myself C++, and found an interesting thing.
According to this web page,:
The most obvious form of iterator is a pointer.
So, I used to think that an iterator object works in almost the same way as a pointer (e.g. int *i);
However, now I guess that it would be more accurate to say an iterator object is like a pointer of a pointer (such as int **i) rather than a pointer (int *i).
I noticed this, when I was coding the following one.
set<Point*, Point> points; //This class encapsulates x and y coordinates for a 2 dimensional point
set<Point*, Point>::iterator it;
int x = 22;
int y = 4;
Point* pt = new Point(x, y);
points.insert(pt);
//Similar statements are here, to insert other Point objects with different arguments
for (it = points.begin(); it != points.end(); it++) {
cout << "**it: " << **it << ", *it :" << *it << ", Address : " << &it << endl;
}
As a result,
**it showed values of Pointer class objects
*it showed addresses
&it showed the address of the it object
So, is it right to say that an iterator object (it) is basically the same as **it?
Another question which is a bit different from iterators:
If I need to make a set of class object, like: set<ClassName*, ClassName> SetName;, what would be the correct way? (as long as this class contains comparable data type, like int or double)
I'd appreciate if you'd give some advice.
It is a wrong assumption. In your example the value_type of the set is pointer Point *. And *it gives you an element in the set that is a reference to some object of this value_type that is of type Point * and ++it "points" to the next element in the set. So the iterator behaves the same way as pointer to an object of value_type.
When you use expression like **it then the second dereference is not applied to the iterator. It is applied to an object in the set. You can imagine expression **it the following way
Point *pp = *it;
Point p = *pp;
Iterator of a container is responsible to provide you access to elements of the container. Thus if elements in the container has type value_type then the iterator provides access to these elements of this value_type. The elements in turn can be pointers to objects or even pointers to pointers to objects and so on.
As for your second question then if the class has the corresponding operator function and the class itself has some simple default constructor then you may use such an approach though it would be better to define a separatw comparator or simply to define operator < for objects of the class. In the last case you can write
std::set<Point> s;
without explicit second template argument.
Here is demonstrative program of your approach
#include <iostream>
#include <set>
int main()
{
struct Point
{
int x, y;
bool operator ()( const Point &p1, const Point &p2 ) const
{
return p1.x < p2.x && p1.y < p2.y;
}
};
std::set<Point, Point> s;
s.insert( { 2, 2 } );
s.insert( { 1, 1 } );
for ( const Point &p : s ) std::cout << p.x << ' ' << p.y << std::endl;
return 0;
}
The program output is
1 1
2 2

Operator overloading in C++ (operator-)

I am working on a program to detect if one triangle is nested within another.
Here I created the struct point to define x and y as doubles.
struct Point {
double x;
double y;
};
Here is where I implement the struct:
double eval (LineSegment line, Point p)
{
Point p1 = p - line.StartPoint;
Point p2 = line.EndPoint - line.StartPoint;
return p2.x * p2.y - p1.y * p2.x;
}
When I compile it tells me, "no match for 'operator-' in 'p - line.LineSegment::StartPoint'."
I don't really understand what is happening, I guess it doesn't understand which 'point' I want since i use them together?
I did research and found operator overloading, but it was sort of confusing to me. I don't really know how to implement Operator Overloading.
If someone could show me how exactly to go about doing this, it would be helpful.
It means that the compiler has no idea how to subtract Point objects. It knows how to subtract built-in types, but to use operators with custom types, you need to provide the behavior.
In this case you probably want something like:
struct Point
{
double x;
double y;
Point& operator-=( const Point& that )
{
x -= that.x;
y -= that.y;
return this;
}
};
Point operator-(Point first, const Point& second)
{
return first -= second;
}
For more guidance, see our C++-FAQ entry on Operator Overloading. Lots of good advice in there that will help you avoid some of the pitfalls, as well as good examples and recommendations how to maximize code re-use and readability (which really means maintainability).
In this case, you should also ask yourself whether you want to differentiate between absolute and relative coordinate pairs. If you do, then the difference between two points should be a Size or Offset, and not a Point. (If you've ever used a library with DateTime and TimeSpan classes, you've seen this concept in action. C++ itself uses it for the Standard Library's time_point vs duration, both found in namespace std::chrono. You have a two dimensional version of that here.)
struct Point {
double x;
double y;
Point operator-(const Point& that) const
{
Point result;
result.x = this->x - that.x;
result.y = this->y - that.y;
return result;
}
};
If you want to subtract points, then you need to provide an overloaded operator to do it. C++ doesn't automatically generate arithmetic operations for class types, since most of the time they wouldn't make sense.
Something like this should do it:
Point operator-(Point lhs, Point rhs) {
return {lhs.x-rhs.x, lhs.y-rhs.y};
}
although I'd probably introduce a new type (Vector or Offset or something) for the return type, to prevent the category error of using the offset between points when you should use a point.
Here's a basic sketch to get you started:
Point operator-( const Point& lhs, const Point& rhs )
{
Point result;
// make sure this is what you want:
result.x = lhs.x - rhs.x;
result.y = lhs.y - rhs.y;
return result;
}
Note this is a free function, it doesn't go inside of Point's definition. Just put it afterwards.
Take a look at http://www.cplusplus.com/doc/tutorial/classes2/. It has a pretty good explanation on operator overloading.
What your code is saying is to subtract line.StartPoint from p. However, your struct doesn't have a defined behavior for that operation. So you can't use the syntax p - line.StartPoint unless you tell the compiler how to perform that operation with your struct.
The method signature in your struct will probably look something like this:
Point operator-(const Point &other) { }
You need to add the logic to that method that tells the compiler how to perform a subtraction operation on your struct.
If you add/subtract/multiply...etc two numbers together the compiler knows what you mean and everything's fine. If you want to subtract something that's a class, the compiler doesn't inherently know how to do that (for ANY class) but gives you a tool to define how to subtract two classes together and it looks like this (using your Point class):
Point operator-(Point p1, Point p2)
{
Point result;
result.x = p1.x - p2.x;
result.y = p1.y - p2.y;
return result;
}
Now the compiler knows how to subtract two points, by calling this function.

Efficient functional style (C++11 ok)

Lets say I have the following:
struct point
{
double x;
double y;
double z;
};
I can write the following:
void point_mult(point& p, double c) { p.x *= c; p.y *= c; p.z *= c; }
void point_add(point& p, const point& p2) { p.x += p2.x; p.y += p2.y; p.z += p2.z; }
So I can then do the following:
point p{1,2,3};
point_mult(p, 2);
point_add(p, point{4,5,6});
This requires no copies of point, and only two constructions, namely the construction of point{1,2,3} and the construction of point{4,5,6}. I believe this applies even if point_add, point_mult and point{...} are in separate compilation units (i.e. can't be inlined).
However, I'd like to write code in a more functional style like this:
point p = point_add(point_mult(point{1,2,3}, 2), point{4,5,6});
How can I write point_mult and point_add such that no copies are required (even if point_mult and point_add are in separate compilation units), or is functional style forced to be not as efficient in C++?
Let's ignore the implicit fallacy of the question (namely that copying automatically means reduced efficiency). And let's also ignore the question of whether any copying would actually happen, or whether it would all be elided away by any half-decent compiler. Let's just take it on face value: can this be done without copying?
Yes, and it is probably the only other legitimate use for r-value references (though the previously ignored stipulations make this use case dubious):
point &&point_mult(point &&p, double c);
Of course, this will only bind to temporaries. So you would need an alternate version for l-values:
point &point_mult(point &p, double c);
The point is that you pass the references through as they are, either as references to temporaries or references to l-values.
It can be done with really ugly template metaprogramming. For example eigen uses templates so that expressions like matrix1 + matrix2 * matrix3 don't need to create any temporaries. The gist of how it works is the + and * operators for matrices don't return Matrix objects but instead return some kind of matrix expression object which is templatized on the types of the expression paramaters. This matrix expression object can then compute parts of the expression only when they are needed instead of creating temporary objects to store the result of subexpressions.
Actually implementing this can get quite messy. Have a look at Eigen's source if your interested. Boost's uBlas also does something similar, though it's not as extensively as eigen.
An efficient (and generalized) technique is expression templates. You can read a nice introductory explanation here.
It's difficult to implement and being based on templates, you cannot use separate compilation units, but it's very efficient. An interesting application in symbolic computation is parsing: Boost.Spirit builds very efficient parsers out of them.
C++11 auto keywords helps usage on practical programming tasks, as always when dealing with complex types, see this other answer.
First, why not use "better" functions ?
struct Point {
double x;
double y;
double z;
Point& operator+=(Point const& right) {
x += right.x; y += right.y; z += right.z;
return *this;
}
Point& operator*=(double f) {
x *= f; y *= f; z *= f;
return *this;
}
};
Now it can be used as:
Point p = ((Point{1,2,3} *= 2) += Point{4,5,6});
But I truly think that you worry too much about copies here (and performance).
Make it work
Make it fast
If you don't have anything that already works, talking about performance is akin to chasing mills... bottlenecks are rarely where we thought they would be.
Change the definition of point_mult() to:
point& point_mult(point& p, double c) { p.x *= c; p.y *= c; p.z *= c; return p; }
^^^^^^ ^^^^^^^^^
And call it as:
point & p = point_add(point_mult(*new point{1,2,3}, 2), point{4,5,6});
^^^ ^^^^^
there is no copy involved. However, you have to later do delete &p; for releasing the memory.

Using pointers for conditional while/for loops gives error when compiling

I'm wondering how to properly use pointers in for and while loops in C++. Usually I write using C instead of C++. The only reason I'm using the C++ std library this time is so I can use the complex number functions required by other mathematical functions in the code.
As part of the assignment we were given the following function declaration. The part that I wrote is commented within the function.
typedef std::complex<double> complex;
// Evaluates a polynomial using Horner's approach.
// Inputs:
// [coeffs, coeffs_end) - polynomial coefficients, ordered by descending power
// x - point of evaluation
// Outputs:
// p - value of polynomial at x
// dp - value of polynomial derivative at x
// ddp - value of polynomials second derivative at x
//
template<typename T>
inline void poly_val(T const* coeffs, T const* coeffs_end, T x, T & p, T & dp, T & ddp)
{
//MY CODE HERE
int i = 0;
const T *pnt = coeffs;
while(pnt != coeffs_end){
//Evaluate coefficients for descending powers
p += coeffs(i)*pow(x,((coeffs_end-1)-i));
pnt++;
i++;
}
}
The function doesn't know the length of the array, so I'm guessing the stop condition is the pointer 'coeffs_end', which points to the last value in the array 'coeffs'. Can I use a pointer in a conditional this way? (traditionally I would have fed the length of the array into the function, but we cant modify the declarations)
If I do it this way I keep get an error when compiling (which I don't get):
C2064:term foes not evaluate to a function taking 1 arguments
for the following line:
p += coeffs(i)*pow(x,((coeffs_end-1)-i));
coeffs(i) is calling convention to a function that takes an integer argument. But in your case it is an pointer. So, you need to use [] operator to access the element at it's index.
Also ((coeffs_end-1)-i) resolves to an address location. You need to dereference it to get the value at the location.
Maybe it'd be more readable to write this in a cleaner fashion:
#include <cmath>
#include <iterator>
template<typename T>
inline void poly_val(T const* coeffs, T const* coeffs_end, T x, T & p, T & dp, T & ddp)
{
const std::size_t nterms = std::distance(coeffs, coeffs_end);
for (std::size_t i = 0; i != nterms; ++i)
{
p += coeffs[i] * std::pow(x, nterms - 1 - i);
}
}
Since raw pointers can be treated as iterators, we can use std::distance to determine the size of an array bounded by a range [first, last).
Edit: Acutally it can be done even easier:
for (const T * it = coeffs; it != coeffs_end; ++it)
{
p += *it * std::pow(x, std::distance(it, coeffs_end) - 1);
}

Why can't I push this object onto my std::list?

Just started programming in C++.
I've created a Point class, a std::list and an iterator like so:
class Point {
public:
int x, y;
Point(int x1, int y1)
{
x = x1;
y = y1;
}
};
std::list <Point> pointList;
std::list <Point>::iterator iter;
I then push new points onto pointList.
Now, I'm needing to iterate through all the points in pointList, so I need to loop using the iterator. This is where I get screwed up.
for(iter = pointList.begin(); iter != pointList.end(); iter++)
{
Point currentPoint = *iter;
glVertex2i(currentPoint.x, currentPoint.y);
}
Update
You guys were right, the problem isn't in my iterating the list. It appears the problem is when I am attempting to push something on to the list.
Exact error:
mouse.cpp: In function void mouseHandler(int, int, int, int)':
mouse.cpp:59: error: conversion fromPoint*' to non-scalar type `Point' requested
Those lines are:
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
Point currentPoint = new Point(x, y);
pointList.push_front(currentPoint);
}
What does it conversion between Point* to non-scalar type Point? I'm just trying to create new points and push them onto the list here.
That should be a valid bit of code.
#include <iostream>
#include <list>
class Point {
public:
int x, y;
Point(int x1, int y1)
{
x = x1;
y = y1;
}
};
int main()
{
std::list<Point> points;
points.push_back(Point(0, 0));
points.push_back(Point(1, 1));
points.push_back(Point(2, 2));
std::list<Point>::iterator iter;
for(iter = points.begin(); iter != points.end(); ++iter)
{
Point test = *iter;
std::cout << test.x << ", " << test.y << "; ";
}
std::cout << std::endl;
return 0;
}
Using this code:
jasons-macbook41:~ g++ test.cpp
jasons-macbook41:~ ./a.out
0, 0; 1, 1; 2, 2;
jasons-macbook41:~
Although I wouldn't create a temporary copy of the Point as your code does. I'd rewrite the loop like this:
for(iter = points.begin(); iter != points.end(); ++iter)
{
std::cout << iter->x << ", " << iter->y << "; ";
}
An iterator is syntactically similar to a pointer.
EDIT:
Given your new problem, drop the "new" from the construction line. That's creating a pointer to a Point, as opposed to a Point on the stack. This would be valid:
Point* temp = new Point(0, 0);
Or this:
Point temp = Point(0, 0);
And you'd be better off with the latter.
a few things..
Did you try iter->x and iter->y instead of copying the value?
the error you mention is hard to understand. You are not trying to get x and y via the iterator, you are copying the iterator data to a new point.
EDIT:
according to new information in the OP. You are trying to new into a non-pointer object and then trying to stuff the point into a vector that only accepts objects. You either have to make the vector a vector of pointers and remember to delete them afterwords or create the new point on the stack and copy them into the vector with a standard assign. Try this:
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
Point currentPoint = Point(x, y);
pointList.push_front(currentPoint);
}
If already have a function you want to apply to a whole list the std::for_each is the way to go, e.g.,
std::for_each(pointList.begin(), pointList.end(), myGreatFunction);
If you have to write the for loop then something like this:
std::list<Point>::iterator itEnd = pointList.end();
for(std::list<Point>::iterator itCur=pointList.begin(); itCur != itEnd; ++itCur) {
yourFunction(itCur->x, itCur->y);
}
Notes:
++itCur can be more efficient than itCur++ due to the return types (reference vs value/copy)
The non-scalar issue is because you're assigning a Point pointer (return value of operator new) to a Point stack object (as it's not Point* in your code).
I would recommend saying
Point currentPoint(x, y);
pointList.push_front(currentPoint);
Note that currentPoint will be copied into your list; the implicitly-generated copy constructor of Point (because you didn't declare a Point(const Point& other) constructor in your class, the compiler did one for you) will copy currentPoint.x and currentPoint.y into the list; in this case, that's fine. Point is small, so the copy expense is low, and it only contains two ints, so a straight up copying of ints is ok.
This answer refers to the edited version of the question.
As gbrandt said in the edited version of his answer, your problem is that you are trying to dynamically allocate an instance of Point and then assign it to a Point object rather than a pointer to Point. The result of new is a pointer to Point, not a Point object -- what you actually want in this case is the latter, which you create without new:
Point currentPoint(x, y);
pointList.push_front(currentPoint);
Because list<T>::push_front() pushes a copy of the Point object on the list, you don't need to do any dynamic allocation here. It's much safer to avoid dynamic allocation when possible as it can easily lead to memory leaks -- e.g. the following alternative code, which compiles and works, results in a memory leak as the object pointed to by currentPoint is never deleted:
Point *currentPoint = new Point(x, y);
pointList.push_front(*currentPoint); // Notice the "*"
Of course you could just add delete currentPoint; to the end to remove the leak, but why use slow dynamic allocation when stack-based allocation does the job faster and more simply?
Here's how I typically approach such loops, if you don't want to use std::foreach:
for (iter curr = pointListObject.begin(), end = pointListObject.end(); curr != end; ++curr)
{
glVertex2i(curr->x, curr->y);
}
Be careful of these points:
pointListObject is an instance of pointList; if you use the class (the type pointList, and not an instance of pointList) you're in troble, but the compiler will whine a lot. Same with iter. It just makes things easier to grok if you keep typenames and instancenames separate.
Doing a joint initialization of the iterators like this lets you keep the initialization of end inside the loop (good for scoping) while keeping the per-loop execution cheap.
Did you cut and paste this code into SO from your .cpp file, or did you retype it? From the sound of your error message, I would guess that the original code says
glVertex2i(iter.x, iter.y);
Which, as gbrandt pointed out, doesn't properly dereference the iterator.
I would rewrite the loop as follows:
std::list<Point>::const_iterator iter = pointList.begin();
const std::list<Point>::const_iterator end = pointList.end();
for (; iter != end; ++iter) {
const Point& p = *iter;
glVertex2i(p.x, p.y);
}
The main changes are to use const_iterators instead of non-const, as your loop doesn't intend to modify the list contents. Then, grab the values of begin() & end() exactly once, use preincrement, and dereference the iterator once into a const reference. This way you have no copying, where your original code copied the Point object that *iter referred to, and you avoid dereferencing the iterator twice for about as much efficiency as you can get here.
Now, for some unsolicited OpenGL advice, I'd also point out that vertex arrays are probably a better choice than immediate mode (glVertex*) calls.
Hope this helps...