c++ - c ++可靠的方法来删除以UUID为键的所有条目
问题描述
所以我有一堆 std::unordered_maps,它们都有一个共同的键,但数据的数据类型不同。我基本上做了一个类似于基于组件的实体系统的结构,关键是一个包含 boost::uuid 的实体类。
添加效果很好,但我正在努力从程序中删除整个实体。我找不到在不损害正在运行的系统的情况下删除它们的可靠方法(我不想允许在帧中间删除以避免由于值不同步或被某些默认值替换而导致一帧出现故障)或这太慢了。
现在我在实体类中有一个布尔值,程序的每一帧都会遍历每个实体并检查它是否设置为真。如果是,则从地图中删除数据点。
然而我对此并不满意。
这是一般实体的样子:
class Entity{
private:
boost::uuids::uuid uuid;
bool protect = false;
bool status = ENTITY_ALIVE;
public:
Entity()
:uuid(boost::uuids::random_generator()()){
}
const boost::uuids::uuid &operator ()()const{
return this->uuid;
}
bool operator ==(const Entity &othr)const{
return this->uuid==othr.uuid;
}
void copyComponents(const Entity &source,ComponentBase** mgrs, int c){
std::cout<<"copying...\n";
for(int i = 0; i < c; i ++){
std::cout<<"-";
mgrs[i]->copyTo(source,*this);
}
}
void kill(){
if(this->protect==false){
this->status = ENTITY_DEAD;
}
}
bool getStatus()const{
return this->status;
}
void setProtection(bool status){
this->protect = status;
}
bool getProtection(){
return this->protect;
}
~Entity(){
// std::cout<<"ENTITY WAS DELETED!!!!!!!!!!!"<<"\n";
}
};
struct EntityHasher{
size_t operator()(const Entity& obj)const{
return boost::uuids::hash_value((obj)());
}
};
好的,这就是地图的样子:
typedef typename std::unordered_map<std::reference_wrapper<const Entity>,List<std::shared_ptr<t>>,EntityHasher,std::equal_to<const Entity>> mapType;
该列表是我制作的一个自定义类,它只是将事物存储在一个双向链表中。没什么好担心的。我这样做是因为访问数据比使用 unordered_multi 地图更容易。
我试过的:
我试图存储指向包含地图的类的链接,并直接让它们删除它而没有太大成功。
我试图这样做时,当访问“死”实体时,它被添加到存储无序映射的类中的向量中,然后在名为“removeCorpses”的单独函数中清除。然而,这会导致较少使用的组件被保留太久,而且它通常真的很不稳定(也许我在实现它时犯了一个错误)
请提出一些好的方法来删除所有地图中的实体,并将其作为键,而不会弄乱活动框架等。
解决方案
您可以使用 Boost.MultiIndex 来构建一个类似地图的结构,使尸体首先排列在二级排序索引中,以便在适当的时候将其擦除:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/member.hpp>
template<typename Key,typename Value>
struct delayed_erasure_unordered_map_value
{
Key first;
mutable Value second;
};
template<typename Key,typename Value>
using delayed_erasure_unordered_map_base=boost::multi_index_container<
delayed_erasure_unordered_map_value<Key,Value>,
boost::multi_index::indexed_by<
boost::multi_index::hashed_unique<
boost::multi_index::member<
delayed_erasure_unordered_map_value<Key,Value>,
Key,
&delayed_erasure_unordered_map_value<Key,Value>::first
>
>,
boost::multi_index::sequenced<>
>
>;
template<typename Key,typename Value>
class delayed_erasure_unordered_map:
public delayed_erasure_unordered_map_base<Key,Value>
{
using base=delayed_erasure_unordered_map_base<Key,Value>;
public:
using iterator=typename base::iterator;
using base::base;
void mark_for_erasure(iterator it) // marking same element twice is UB
{
auto pit=this->template project<1>(it);
auto& index=this->template get<1>();
index.relocate(index.begin(),pit);
++num_corpses;
}
void erase_marked()
{
auto& index=this->template get<1>();
for(;num_corpses;--num_corpses)index.erase(index.begin());
}
private:
std::size_t num_corpses=0;
};
#include <iostream>
int main()
{
delayed_erasure_unordered_map<int,int> m=
{{0,0},{1,1},{2,2},{3,3},{4,4},{5,5},{6,6},{7,7},{8,8},{9,9}};
for(auto it=m.begin(),end=m.end();it!=end;++it){
if(it->first%2)m.mark_for_erasure(it);
}
m.erase_marked();
for(const auto& x:m){
std::cout<<"{"<<x.first<<","<<x.second<<"} ";
}
}
输出
{0,0} {2,2} {4,4} {6,6} {8,8}
推荐阅读
- wpf - WPF CaptureMouse 不会在主窗口之外捕获鼠标事件
- asp.net-mvc - 我无法配置路由
- ruby - 根据某些条件匹配每个值的区域
- javascript - 组件在刷新时丢失收到的道具
- javascript - 从扩展中获取当前 URL?
- swift - 升级到 Xcode 10.2 时遇到问题
- sql - 如何在 SQLlite 中获得 X 列与 Y 列的比率?
- python - 为什么我会收到 ModuleNotFoundError(Flask 和 Heroku)
- c# - ASP.NET Core 2.2 - 当浏览器(IE11 和 Edge)禁用 cookie 时是否可以使用 cookie 身份验证?
- python - 如何阻止随机项目被打印出一个字母一个字母