C++迭代集合

发布于 2024-10-20 14:24:31 字数 880 浏览 5 评论 0原文

我最近更改了一些代码以使用集合而不是向量:

std::set<b2Body *>toDestroy;
//std::vector<b2Body *>toDestroy;

但现在我不确定如何迭代集合来查找对象。这就是我所拥有的:

std::vector<b2Body *>::iterator pos2;
    for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
        b2Body *body = *pos2;     
        if (body->GetUserData() != NULL) {
            CCSprite *sprite = (CCSprite *) body->GetUserData();
            [self removeChild:sprite cleanup:YES];
        }
        _world->DestroyBody(body);
    }

既然 toDestroy 是一个集合,那么等效的是什么?来自 Objective-C,所以我只是学习 C++ 的最佳实践。

编辑:添加我收到的错误消息:

error: no match for 'operator=' in 'pos2 = toDestroy. std::set<_Key, _Compare, _Alloc>::begin [with _Key = b2Body*, _Compare = std::less<b2Body*>, _Alloc = std::allocator<b2Body*>]()'

I recently changed some code to use a set instead of a vector:

std::set<b2Body *>toDestroy;
//std::vector<b2Body *>toDestroy;

But now I'm not sure how to iterate the set to find objects. This is what I had:

std::vector<b2Body *>::iterator pos2;
    for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
        b2Body *body = *pos2;     
        if (body->GetUserData() != NULL) {
            CCSprite *sprite = (CCSprite *) body->GetUserData();
            [self removeChild:sprite cleanup:YES];
        }
        _world->DestroyBody(body);
    }

What is the equivalent now that toDestroy is a set? Coming from Objective-C so I'm just learning best practices in C++.

EDIT: adding the error message I get:

error: no match for 'operator=' in 'pos2 = toDestroy. std::set<_Key, _Compare, _Alloc>::begin [with _Key = b2Body*, _Compare = std::less<b2Body*>, _Alloc = std::allocator<b2Body*>]()'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

当梦初醒 2024-10-27 14:24:31

您需要将迭代器声明为 set 迭代器:

更改

std::vector<b2Body *>::iterator pos2;

std::set<b2Body *>::iterator pos2;

You need to declare your iterator to be a set iterator:

Change

std::vector<b2Body *>::iterator pos2;

to

std::set<b2Body *>::iterator pos2;
无法言说的痛 2024-10-27 14:24:31

使用 C++11 你可以简单地写:

    for(auto pos2:toDestroy)

With C++11 you could simply write:

    for(auto pos2:toDestroy)
不爱素颜 2024-10-27 14:24:31

通过集合的迭代将像向量存在时一样工作,因此无需更改代码。

我会注意 DestroyBody 中发生的情况(调用是否从向量或集合中删除元素,从而使迭代器无效?)

此外,向量、集合或列表的使用取决于用法:

  • 如果b2Body 对象是提前知道的,因此可以提前保留容量,并且不会经常发生新的插入删除,或者如果您需要随机访问向量的元素(没有迭代器),
  • 如果元素数量不是,我会使用列表提前知道和/或插入和删除经常发生,
  • 如果我需要迭代元素的有序列表,或者例如,如果我需要应用程序查找某些数据是否已被处理并且位于集合中,我会使用集合(在集合上查找的方法很快)

我认为这里最合适的容器是列表(并且迭代代码仍然不需要更改)

The iteration through the set will work as when the vector is there, so there is no need to change the code.

I would pay attention to what happen in DestroyBody (does the call remove the element from the vector or set, invalidating the iterator?)

Also the usage of vector, set or list depend on the usage:

  • I would use a vector if the number of b2Body objects is known in advance so the capacity can be reserved in advance and new insertion deletion don't happen often, or if you need to access the vector's element randomly (without iterator)
  • I would use the list if the number of elements is not known in advance and/or insertion and deletion happen often
  • I would use the set if I need to iterate through an ordered list of element or for instance if I need the application to find if some data has already been processed and is in the set (the method find on the set is fast)

I think that the most appropriate container here is the list (and still the iteration code wouldn't need to be changed)

貪欢 2024-10-27 14:24:31

很多时候值得对模板化容器类型进行类型定义(特别是在类内部使用时)。

typedef std::set<b2Body *>   BodyCont;
//typedef std::vector<b2Body *>   BodyCont;
BodyCont                toDestroy;

那么您的其他代码就不需要修改:

BodyCont::iterator pos2;

如果您可以将 typedef 设为私有,那么您就知道实现细节不会逃逸该类。如果您需要公开 typedef,那么您就知道您正在泄漏实现细节,并且需要了解原因以及是否可以加强您的设计。

A lot of time it is worth type-defing templated container types (especially when used inside a class).

typedef std::set<b2Body *>   BodyCont;
//typedef std::vector<b2Body *>   BodyCont;
BodyCont                toDestroy;

Then your other code would have not needed modifying:

BodyCont::iterator pos2;

If you can make the typedef private then you know that implementation details are not escaping the class. If you need to make the typedef public then you know you are leaking implementation details and need to understand why and if you can tighten your design.

迷爱 2024-10-27 14:24:31

从 C++11 开始,当迭代容器时,应该使用“auto”来声明迭代器。
在你的情况下,“for”行可以写成这样:
for(auto pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2)

Since C++11, when iterating over a container, you should use "auto" to declare an iterator.
In your case, the "for" line can be written like this:
for(auto pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文