如何使用迭代器?

我正在计算两点之间的距离。我在 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;
}
45787 次浏览

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

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

您的代码之所以能够编译,可能是因为您在某个地方有一个 using namespace std。(否则 vector将不得不是 std::vector。)你刚才提供了一个很好的例子,为什么:
偶然地,您的调用获取 std::distance(),它采用两个迭代器并计算它们之间的距离。删除 using 指令并在所有标准库类型前加上 std::的前缀,编译器将告诉您您试图在需要 point*的地方传递 vector <point>::iterator

要获得迭代器指向的对象的指针,您必须取消对迭代器的引用(它提供对对象的引用) ,并获取结果的地址: &*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 这个答案 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));
}

请注意,这些点是由 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 编译器来说无论如何都是一个更大的挑战。

你可以做几件事:

  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. Dereference your iterators when calling distance()so you're passing the point objects:
    distance( *ii, *jj)
    
    如果不更改 distance()函数的接口,则可能需要更改 必须使用下面这样的东西来称之为合适的 提示:
    distance( &*ii, &*jj)