Programing

반복자를 사용하는 방법?

crosscheck 2020. 10. 31. 09:22
반응형

반복자를 사용하는 방법?


두 점 사이의 거리를 계산하려고합니다. 내가 C ++의 벡터에 저장 한 두 점 : (0,0)과 (1,1).

나는 결과를 얻어야한다.

0
1.4
1.4
0

하지만 내가 얻은 실제 결과는

0
1
-1
0

벡터에서 반복기를 사용하는 방식에 문제가 있다고 생각합니다. 이 문제를 어떻게 해결할 수 있습니까?

아래 코드를 게시했습니다.

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()은 두 개의 반복자를 취하고 그들 사이의 거리를 계산하는을 픽업 합니다. using 지시문을 제거하고 모든 표준 라이브러리 유형을 접두사로 지정 std::하면 컴파일러 vector <point>::iterator에서 a point*가 필요한 위치 를 전달하려고했다고 알려줍니다 .

반복기가 가리키는 객체에 대한 포인터를 얻으려면 객체에 대한 참조를 제공하는 반복기를 역 참조하고 결과 주소를 가져와야 &*ii합니다..
(포인터는 std::vector반복기에 대한 모든 요구 사항을 완벽하게 충족 하고 표준 라이브러리의 일부 이전 구현에서는 실제로 포인터를 사용하여 std::vector반복기를 포인터 로 처리 할 수있었습니다 . 그러나 현대 구현에서는이를 위해 특수 반복기 클래스를 사용합니다. 이유는 클래스를 사용하면 포인터와 반복자에 대한 함수 오버로딩이 가능하기 때문입니다. 또한 포인터를 std::vector반복자 로 사용하면 포인터와 반복자가 혼합되어 컨테이너를 변경할 때 코드가 컴파일되지 않습니다.)

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:

  1. 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(point const& p1, point const& p2)
    {
        return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
                    (p1.y - p2.y)*(p1.y - p2.y));
    }
    
  2. 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)

참고URL : https://stackoverflow.com/questions/2712076/how-to-use-an-iterator

반응형