76

我正在尝试计算两点之间的距离。我在 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;
}
4

3 回答 3

205

您的代码完全编译可能是因为您有一个using namespace std地方。(否则vector必须是std::vector。)这是我不建议的事情,您刚刚提供了一个很好的案例,原因是:
意外地,您的电话接听std::distance(),这需要两个迭代器并计算它们之间的距离。删除 using 指令并为所有标准库类型添加前缀std::,编译器会告诉您您尝试在需要 a 的vector <point>::iterator地方传递 a 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 编译器来说将是一个更大的挑战。

于 2010-04-26T08:50:52.773 回答
21

巧合的是,您实际上使用的是内置 STL 函数 "distance",它计算迭代器之间的距离,而不是调用您自己的距离函数。您需要“取消引用”您的迭代器以获取包含的对象。

cout << distance(&(*ii), &(*jj)) << " ";

从上面的语法可以看出,“迭代器”很像广义的“指针”。迭代器不能直接用作“你的”对象类型。事实上,迭代器与指针非常相似,以至于许多对迭代器进行操作的标准算法也可以在指针上正常工作。

正如 Sbi 指出的:您的距离函数需要指针。最好将其重写为采用 const 引用,这将使函数更“规范”c++,并使迭代器取消引用语法不那么痛苦。

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) << " ";
于 2010-04-26T08:48:52.657 回答
6

你可能会做几件事:

  1. 使distance()函数引用point对象。这实际上只是为了在调用distance()函数时使事情更具可读性:
    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));
    }
    
  2. 调用时取消引用您的迭代器,distance()以便您传递point对象:
    distance( *ii, *jj)
    
    如果您不更改distance()函数的接口,则可能必须使用以下方式调用它以获得适当的指针:
    distance( &*ii, &*jj)
    
于 2010-04-26T08:55:39.737 回答