C++ 如何使用迭代器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2712076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use an iterator?
提问by sbi
I'm trying to calculate the distance between two points. The two points I stored in a vector in C++: (0,0) and (1,1).
我正在尝试计算两点之间的距离。我在 C++ 中存储在向量中的两个点:(0,0) 和 (1,1)。
I'm supposed to get results as
我应该得到结果
0
1.4
1.4
0
But the actual result that I got is
但我得到的实际结果是
0
1
-1
0
I think there's something wrong with the way I use iterator in vector. How can I fix this problem?
我认为我在向量中使用迭代器的方式有问题。我该如何解决这个问题?
I posted the code below.
我在下面发布了代码。
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;
}
回答by sbi
That your code compiles at all is probably because you have a using namespace std
somewhere. (Otherwise vector
would have to be std::vector
.) That's something I would advise againstand you have just provided a good case why:
By accident, your call picks up std::distance()
, which takes two iterators and calculates the distance between them. Remove the using directive and prefix all standard library types with std::
and the compiler will tell you that you tried to pass a vector <point>::iterator
where a point*
was required.
你的代码完全编译可能是因为你有一个using namespace std
地方。(否则vector
必须是std::vector
。)这是我建议反对的事情,您刚刚提供了一个很好的案例原因:
偶然地,您的电话会拿起std::distance()
,它需要两个迭代器并计算它们之间的距离。删除 using 指令并为所有标准库类型添加前缀std::
,编译器会告诉您您试图在需要a 的vector <point>::iterator
地方传递 a point*
。
To get a pointer to an object an iterator points to, you'd have to dereference the iterator - which gives a reference to the object - and take the address of the result: &*ii
.
(Note that a pointer would perfectly fulfill all requirements for a std::vector
iterator and some earlier implementations of the standard library indeed used pointers for that, which allowed you to treat std::vector
iterators as pointers. But modern implementations use a special iterator class for that. I suppose the reason is that using a class allows overloading functions for pointers and iterators. Also, using pointers as std::vector
iterators encourages mixing pointers and iterators, which will prevent the code to compile when you change your container.)
要获得指向迭代器指向的对象的指针,您必须取消引用迭代器(它提供对对象的引用)并获取结果的地址:&*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 answerfor 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.
请注意,这些点是通过const
引用获得的。这向调用者表明该函数不会改变它传递的点数。
Then you can call it like this: distance(*ii,*jj)
.
然后,你可以这样调用: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
是 C++ 中不必要的 C-ism。拼一下就行
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.
如果这个struct
定义要从 C 编译器解析(代码必须引用struct point
那时,而不是简单地point
),那会产生问题,但我猜std::vector
无论如何对 C 编译器来说都是一个更大的挑战。
回答by Joris Timmermans
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.
巧合的是,您实际上使用的是内置的 STL 函数 "distance",它计算迭代器之间的距离,而不是调用您自己的距离函数。您需要“取消引用”您的迭代器以获取包含的对象。
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.
正如 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) << " ";
回答by Michael Burr
You might do a couple of things:
你可能会做几件事:
- Make the
distance()
function take references topoint
objects. This is really just to make things more readable when calling thedistance()
function: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)); }
- Dereference your iterators when calling
distance()
so you're passing thepoint
objects:
If you don't change the interface of thedistance( *ii, *jj)
distance()
function, you might have to call it using something like the following to get appropriate pointers:distance( &*ii, &*jj)
- 使
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)); }
- 调用时取消引用迭代器,
distance()
以便传递point
对象:
如果您不更改distance( *ii, *jj)
distance()
函数的接口,则可能必须使用类似以下内容来调用它以获取适当的指针:distance( &*ii, &*jj)