+2  A: 

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);
}
gbrandt
the first point is pretty much moot as the standard dictates that end() is a O(1) operation. Plus every decent compiler out there will optimize it quite nicely. Point #2 is the real problem he has.
Evan Teran
the compiler cannot optimize it out because it does not know that the function call returns a constant (in this case). So in the very least it has to make the function call, costing a branch and return and stack manipulation. This can be costly depending on CPU pipe lining.
gbrandt
yes it does because the function is const meaning that it doesn't change the state of the object.
Evan Teran
I recommend you look at the assembly output of pre-calculating it and compare to not, you'll find they are more or less identical.
Evan Teran
the return of size is not const, just the definition of method size is const, this means the class is const safe for this call. ie const vector x; x.size is a legal call. The function call will still be made becaue the data it returns is not const
gbrandt
end() != size(), if you actually **test** it you'll find that as long as you don't modify the container, the compiler will be smart enough not to call it every time. In fact, most of the time, it'll be inlined completely.
Evan Teran
The following 2 programs produced *identical* assembly with g++ -O3: http://rafb.net/p/e32cuR54.html. Test your theories before claiming that they are true.
Evan Teran
GCC 4.01 with g++ -O3 -S produces different assembly outputs and different binaries with vectors and lists. GCC 4.2 produces identical output for lists but different output for vectors. The OP uses a vector, my comment stands.
gbrandt
First of all, the OP used a std::list, not a std::vector. Secondly, you'll find that even when they are different, the difference is small and not a repetitive call to the end() function. Your comment is still wrong.
Evan Teran
If you read the header implementing end(), you'll see:iterator end() { return }or:iterator end() { return iterator (this->_M_impl._M_finish); }There's no way that can be anything other than O(1).
jasedit
Your latest edit contains the key information. Unfortunately my +1 only brought this answer to 0...
j_random_hacker
+1  A: 

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)
maccullt
This is a good answer on helping me with my iteration, thank you
KingNestor
A: 

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.
Matt
+2  A: 

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.

jasedit
+1  A: 

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.

Matt
A: 

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...

Drew Hall
+1  A: 

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?

j_random_hacker