4

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ポイント*'から非スカラータイプの`ポイント'が要求されました

それらの行は次のとおりです。

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

}

Point *から非スカラータイプのPointへの変換は何ですか?新しいポイントを作成して、ここのリストにプッシュしようとしています。

4

7 に答える 7

2

いくつかのこと..

  • 値をコピーする代わりに、iter->x試しましたか?iter->y
  • あなたが言及するエラーは理解するのが難しいです。イテレータを介してxとyを取得しようとしているのではなく、イテレータデータを新しいポイントにコピーしています。

編集:

OPの新しい情報によると。ポインタ以外のオブジェクトを新しく作成してから、オブジェクトのみを受け入れるベクトルにポイントを詰め込もうとしています。ベクトルをポインタのベクトルにして、単語の後に削除することを忘れないか、スタック上に新しいポイントを作成して、標準の割り当てを使用してベクトルにコピーする必要があります。これを試して:

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
    Point currentPoint = Point(x, y);
    pointList.push_front(currentPoint);
}
于 2009-02-11T02:50:48.767 に答える
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* temp = new Point(0, 0);

またはこれ:

Point temp = Point(0, 0);

そして、あなたは後者の方が良いでしょう。

于 2009-02-11T03:03:19.440 に答える
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++よりも効率的です。
于 2009-02-11T03:00:39.040 に答える
1

非スカラーの問題は、Pointポインター(演算子newの戻り値)をPointスタックオブジェクトに割り当てているためです(コード内のPoint *ではないため)。

私は言うことをお勧めします

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

currentPointがリストにコピーされることに注意してください。暗黙的に生成されたPointのコピーコンストラクター(クラスでPoint(const Point&other)コンストラクターを宣言しなかったため、コンパイラーが宣言しました)は、currentPoint.xとcurrentPoint.yをリストにコピーします。この場合、それは問題ありません。ポイントが小さいのでコピー費用が少なく、intが2つしかないので、intを真っ直ぐにコピーしても大丈夫です。

于 2009-02-11T03:07:14.687 に答える
1

この回答は、質問の編集版を参照しています。

gbrandtが彼の回答の編集版で言ったように、あなたの問題は、のインスタンスを動的に割り当ててから、へのポインタではなくオブジェクトPointに割り当てようとしていることです。の結果は へのポインタであり、オブジェクトではありません。この場合に実際に必要なのは後者であり、 を使用せずに作成します。Point Pointnew PointPointnew

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

リストにオブジェクトのコピーlist<T>::push_front()プッシュするため、ここで動的割り当てを行う必要はありません。可能な場合は動的割り当てを避ける方が安全です。メモリ リークが発生しやすいためです。たとえば、コンパイルして動作する次の代替コードでは、 が指すオブジェクトがdにならないため、メモリ リークが発生します。PointcurrentPointdelete

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

もちろんdelete currentPoint;、最後に追加してリークを取り除くこともできますが、スタックベースの割り当てがより高速かつ簡単に機能するのに、なぜ遅い動的割り当てを使用するのでしょうか?

于 2009-02-11T04:46:46.117 に答える
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の初期化を維持できます(スコープに適しています)。
于 2009-02-11T03:02:33.420 に答える
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 の代わりに const_iterators を使用することです。次に、begin() と end() の値を 1 回だけ取得し、プリインクリメントを使用して、反復子を 1 回逆参照して const 参照にします。このようにして、元のコードが *iter が参照する Point オブジェクトをコピーしたコピーがなくなり、イテレータを 2 回逆参照することを回避して、ここで得られる効率とほぼ同じになります。

ここで、OpenGL の一方的なアドバイスとして、頂点配列はおそらくイミディエイト モード (glVertex*) 呼び出しよりも適切な選択であることも指摘します。

お役に立てれば...

于 2009-02-11T03:24:25.567 に答える