1. ホーム
  2. c++

イテレータを使うには?

2023-08-13 20:56:09

質問

私は2点間の距離を計算しようとしています。私はC + +でベクトルに格納されている2つの点:(0,0)と(1,1)。

私は次のような結果を得ることになっています。

0
1.4
1.4
0

しかし、実際に得られた結果は

0
1
-1
0

vectorでのiteratorの使い方がおかしいと思います。 どうしたらこの問題を解決できますか?

下にコードを載せました。

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

どのように解決するのですか?

あなたのコードが全くコンパイルされないのは、おそらくあなたが using namespace std がどこかにあるからでしょう。(そうでなければ vector にしなければならないでしょう。 std::vector .) それは私が忠告したいことです そして、あなたはその良い事例を提供してくれました。

偶然にも、あなたの電話がかかってきました。 std::distance() これは2つのイテレータを取り、それらの間の距離を計算します。usingディレクティブを削除し、すべての標準ライブラリ型のプレフィクスとして std:: を渡そうとすると、コンパイラはそのことを教えてくれます。 vector <point>::iterator を渡そうとしたと point* が必要でした。

イテレータが指すオブジェクトへのポインタを得るには、オブジェクトへの参照を与えるイテレータの参照を解除し、その結果のアドレスを取得する必要があります。 &*ii .

(なお、ポインタは std::vector イテレータのすべての要件を完全に満たすものであり、標準ライブラリの初期の実装では実際にそのためにポインタが使用されており、これにより std::vector イテレータをポインタとして扱うことができました。しかし、最近の実装では、そのために特別なイテレータクラスを使用しています。クラスを使うことで、ポインタやイテレータの関数をオーバーロードすることができるからだろう。また、ポインタを std::vector イテレータとして使用すると、ポインタとイテレータの混在が助長され、コンテナを変更したときにコードがコンパイルできなくなります(笑)。

しかし、このようなことをするよりも、代わりに参照を受け取るように関数を変更することをお勧めします ( この回答 をご覧ください)。:

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

なお、ポイントは const の参照で取られていることに注意してください。これは呼び出し側に対して、この関数が渡されたポイントを変更しないことを示す。

では、このように呼び出すことができます。 distance(*ii,*jj) .


余談ですが、この

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

はC++では不要なC言語イズムです。ただ、スペル

struct point {
    float x;
    float y;
};

というのは、もしこの struct の定義が C コンパイラでパースされた場合、問題が生じます(コードは struct point を参照しなければなりませんが、単に point を意味する) が、おそらく std::vector などは、C コンパイラにとってはるかに困難なものでしょう。