![](/img/trans.png)
[英]Assign std::vector<std::unique_ptr<T>> to another std::vector<std::unique_ptr<T>>
[英]Any better alternative to std::vector<std::unique_ptr<T>>?
我正在寻找一个需要满足以下要求的容器(针对游戏开发,尤其是实体管理) :
例:
Container<Entity> container;
// This pointer will always point to the player
Entity* player{new Entity};
container.add(player);
// Set some entities to "dead"
for(auto& e : container) if(e->type == "Enemy") e->die();
// Use erase-remove idiom on "dead" entities
container.cleanup();
// Player pointer is still valid
player->doSomething();
到目前为止,我已经尝试了两种不同的容器类型:
std::vector<std::unique_ptr<T>>
std::unique_ptr
) std::unique_ptr
) ...和...
std::list<T>
即使看起来违反直觉, 根据我的基准 , std::vector<std::unique_ptr<T>>
比std::list<T>
性能更高。
(对于较大的类型, std::list<T>
在插入过程中性能更高,但std::vector<std::unique_ptr<T>>
仍然是赢家) 。
我想知道是否有更好的替代std::vector<std::unique_ptr<T>>
。
理想地,替代方案应该是高速缓存友好的 ,以实现快速迭代,并且即使在添加/删除现有项目之后,用户也可以引用相同的项目(指针不应无效) 。
通过性能测试,您正在做正确的事情。 那是回答这个问题的唯一真实方法。
我所知道的唯一可能更快的方法是创建一个缓冲区。 然后为vector<unique_ptr<T>, custom_allocator<unique_ptr<T>>>
创建一个自定义分配器,该分配器从缓冲区分配。
还从同一缓冲区分配对象(这样,将unique_ptr的点指向缓冲区)。
为此,您必须知道上限,或者为超出限制时编写溢出逻辑。
使自定义分配器从缓冲区的中间向上增长。
使unique_ptrs的分配从缓冲区的中间向下增加。
只要整个缓冲区都适合高速缓存行,您就会尽可能快。 这并非易事,而且您当前的解决方案可能已经足够好了。
这听起来像是普通的std :: vector是您想要的。
到目前为止,这是最快的迭代,因为您需要对内存的连续部分进行一次扫描。 您只能通过研究T的结构来做得更好。
可以使用O(1)中的push_back插入新元素。 可以通过O(1)中的swap和pop_back的组合来删除单个元素。 可以使用remove_if和擦除组合删除几个元素。
您不能存储指针,因为它们将无效。 但是,您可以做的是存储索引并使向量几乎全局可用。
使用索引代替指针还有两个优点:
为了说明第2点,请看以下两个示例
struct Unit{
int type, health;
};
vector<Unit>units;
for(int i=0; i<(int)units.size(); ++i)
if(units[i].type == medic)
units[i].health += 10;
与
vector<int>type, health;
for(int i=0; i<(int)type.size(); ++i)
if(type[i] == medic)
health[i] += 10;
假设只有很少的医生。 在第一个代码段中,由于类型和运行状况值在内存中相邻,因此必须通过缓存将整个内存通过管道传输。 在第二个示例中,只需要加载所有类型的数据,而医疗人员的健康值很少。 总的来说,需要加载的内存更少,这导致了更快的迭代。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.