为什么我不能把这个对象推到我的std :: list上?

时间:2009-02-11 02:46:18

标签: c++ linked-list loops

刚开始用C ++编程。

我创建了一个Point类,一个std :: list和一个像这样的迭代器:

class Point { 
public:
    int x, y;
    Point(int x1, int y1)
    {
        x = x1;
        y = y1;
    }
};

std::list <Point> pointList;
std::list <Point>::iterator iter;

然后我将新点推到pointList。

现在,我需要遍历pointList中的所有点,所以我需要使用迭代器进行循环。这是我搞砸的地方。

for(iter = pointList.begin(); iter != pointList.end(); iter++)
{
    Point currentPoint = *iter;
    glVertex2i(currentPoint.x, currentPoint.y);
}

<击>


更新

你们是对的,问题不在我的迭代列表中。看来问题是当我试图将某些内容推到列表中时。

确切错误:

  

mouse.cpp:在函数void mouseHandler(int, int, int, int)': mouse.cpp:59: error: conversion from Point *'到非标量类型`Point'请求

这些行是:

 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
    Point currentPoint = new Point(x, y);
    pointList.push_front(currentPoint);

}

Point *与非标量类型Point之间的转换是什么?我只是想创建新的点并将它们推到列表中。

7 个答案:

答案 0 :(得分:2)

一些事情..

  • 您是否尝试iter->xiter->y而不是复制值?
  • 你提到的错误很难理解。您不是试图通过迭代器获取x和y,而是将迭代器数据复制到新的点。

编辑:

根据OP中的新信息。您正在尝试新建一个非指针对象,然后尝试将该点填充到只接受对象的向量中。你要么必须使向量成为指针的向量,要么记住在词后删除它们或在堆栈上创建新点并将它们复制到带有标准赋值的向量中。试试这个:

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
    Point currentPoint = Point(x, y);
    pointList.push_front(currentPoint);
}

答案 1 :(得分:2)

那应该是有效的代码。

#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;
}

使用此代码:

jasons-macbook41:~ g++ test.cpp
jasons-macbook41:~ ./a.out
0, 0; 1, 1; 2, 2; 
jasons-macbook41:~ 

虽然我不会像你的代码那样创建Point的临时副本。我会像这样重写循环:

for(iter = points.begin(); iter != points.end(); ++iter)
{
    std::cout << iter->x << ", " << iter->y << "; ";
}

迭代器在语法上类似于指针。

编辑: 鉴于您的新问题,请从构造线中删除“新”。这是创建指向Point的指针,而不是堆栈上的Point。这是有效的:

Point* temp = new Point(0, 0);

或者这个:

Point temp = Point(0, 0);

你最好还是后者。

答案 2 :(得分:1)

如果您已经有一个想要应用于整个列表的函数,那么std :: for_each就是要走的路,例如,

std::for_each(pointList.begin(), pointList.end(), myGreatFunction);

如果你必须编写for循环,那么就像这样:

std::list<Point>::iterator itEnd = pointList.end();
for(std::list<Point>::iterator itCur=pointList.begin(); itCur != itEnd; ++itCur) {
    yourFunction(itCur->x, itCur->y);
}

注意:

  • ++ itCur比itCur ++更有效,因为返回类型(引用vs值/副本)

答案 3 :(得分:1)

非标量问题是因为您将Point指针(operator new的返回值)分配给Point堆栈对象(因为它不是代码中的Point *)。

我建议说

    Point currentPoint(x, y);
    pointList.push_front(currentPoint);

请注意,currentPoint将复制到您的列表中; Point的隐式生成的复制构造函数(因为你没有在类中声明一个Point(const Point&amp; other)构造函数,编译器为你做了一个)将currentPoint.x和currentPoint.y复制到列表中;在这种情况下,那没关系。点很小,因此复制费用很低,而且它只包含两个整数,因此可以直接复制整数。

答案 4 :(得分:1)

此答案指的是问题的编辑版本。

正如gbrandt在他的答案的编辑版中所说,你的问题是你正在尝试动态分配Point的实例,然后将其分配给Point 对象而不是指向 Point指针。 new的结果是指向 Point指针,而不是Point对象 - 在这种情况下您真正想要的是后者,您在没有new

Point currentPoint(x, y);
pointList.push_front(currentPoint);

由于list<T>::push_front()推送了列表中Point对象的副本,因此您无需在此处进行任何动态分配。在可能的情况下避免动态分配更安全,因为它很容易导致内存泄漏 - 例如以下替代代码(编译和工作)导致内存泄漏,因为currentPoint指向的对象永远不会delete d:

Point *currentPoint = new Point(x, y);
pointList.push_front(*currentPoint);      // Notice the "*"

当然你可以在末尾添加delete currentPoint;以消除泄漏,但是为什么在基于堆栈的分配能够更快,更简单地完成工作时使用慢动态分配?

答案 5 :(得分:0)

如果你不想使用std :: foreach ,这就是我通常如何处理这样的循环

for (iter curr = pointListObject.begin(), end = pointListObject.end(); curr != end; ++curr)
{
    glVertex2i(curr->x, curr->y);
}

小心这些要点:

  • pointListObject是pointList的一个实例;如果你使用类(类型为pointList,而不是pointList的实例),那么你就会陷入困境,但编译器会抱怨很多。与iter相同。如果你将类型名和实例名分开,它只会让事情变得更容易。
  • 对这样的迭代器进行联合初始化可以让你在循环内保持end的初始化(适用于作用域),同时保持每循环执行的便宜。

答案 6 :(得分:0)

您是否已将此代码剪切并粘贴到.cpp文件中的SO中,或者您是否重新键入了该代码?从您的错误消息的声音,我猜想原始代码说

glVertex2i(iter.x, iter.y);

正如gbrandt指出的那样,它没有正确地解引用迭代器。

我会按如下方式重写循环:

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

主要的变化是使用const_iterators而不是非const,因为你的循环不打算修改列表内容。然后,抓住begin()&amp;的值。 end()恰好一次,使用preincrement,并将迭代器解引用一次到const引用中。这样你就没有复制了,你的原始代码复制了* iter所引用的Point对象,并且你可以避免两次取消引用迭代器,效率和你在这里一样多。

现在,对于一些未经请求的OpenGL建议,我还指出顶点数组可能是比立即模式(glVertex *)调用更好的选择。

希望这会有所帮助......