C++ 在std::map中存储结构实例

C++ 在std::map中存储结构实例,c++,templates,stl,struct,C++,Templates,Stl,Struct,我正在尝试将一些结构映射到其他实例,如下所示: template <typename T> class Component { public: typedef std::map<EntityID, T> instances_map; instances_map instances; Component() {}; T add(EntityID id) { T* t = new T(); instanc

我正在尝试将一些结构映射到其他实例,如下所示:

template <typename T>
class Component {
public:

    typedef std::map<EntityID, T> instances_map;

    instances_map instances;

    Component() {};

    T add(EntityID id) {
        T* t = new T();
        instances[id] = *t;
        return *t;
    };  
};
struct UnitInfos {
    int owner_id;
    int health;
    float x, y;
};

class LogicComponent : public Component<UnitInfos> {};
comp.instance[id];
我得到一个新的breand对象,其属性初始化为默认值

这段代码是否存在固有的问题,或者我是否遗漏了有关问题的信息


根据@aaa建议,我将代码更改为

typedef std::map<EntityID, T> instances_map;
instances_map instances;
T& add(EntityID id) {
    instances[id] = T();
    return instances[id];
};
info.x的值仍然是0。有什么建议吗


问题是我如何将对LogicComponent的引用存储在另一个类中。使用
LogicComponent logic\u c而不是
逻辑组件和逻辑。它现在可以工作了,但我正在地图中存储指针(而不是@aaa的建议)。这是个坏主意吗?

可能是这样

T add(EntityID id) {
    T* t = new T();
    instances[id] = *t;
    return *t;  // return value and map instance are not the same anymore
};  
应该是

T& add(EntityID id) {
    instances[id] = T();
    return instances[id];
};  

听起来您将索引运算符定义为:

template <typename T>
T& Component::operator[]( EntityID id )
{
    return instances[id];
}
这样,当您尝试通过不存在的键进行检索时,将出现异常。更好的是,只需像下面那样使用
typedef
即可:

typedef std::map<EntityID,UnitInfos> EntityUnitMap;
typedef std::map EntityUnitMap;

其他人已经提到,您不需要动态分配对象—您将副本存储在容器中—并且这样做时会泄漏内存。

阐明您希望在LogicComponent上执行的操作。假设您正试图实现以下目标:

步骤1:向地图添加新条目:

LogicComponent comp; 
EntityID id = 99;
UnitInfos info = comp.add(id);
步骤2:初始化信息:

info.x = 10.0;
info.y = 11.0
// etc
步骤3:再次获取信息对象:

UnitInfos info2 = comp.instances[id]; // this is uninitialized.
然后,依次列出一些代码注释:

comp.add返回的信息对象是您添加到地图中的对象的副本。通过修改它,您并不是在修改地图中的内容

最简单的修复方法是创建指向对象的指针映射,而不是对象本身

typedef std::map<EntityID, T*> pinstances_map;

T * add(EntityID id) {
    T* t = new T();
    instances[id] = t;
    return t;
};  

// initialize as 
UnitInfo *info = comp.add(id);
info->x = 10.0;
info->y = 11.0;

// retrieve as 
UnitInfos *info = comp.instances[id];
typedef std::map pinstances\u map;
T*add(EntityID){
T*T=新的T();
实例[id]=t;
返回t;
};  
//初始化为
UnitInfo*info=comp.add(id);
信息->x=10.0;
信息->y=11.0;
//检索为
UnitInfo*信息=组件实例[id];
另外,请使用访问器方法获取映射值,而不是将映射对象公开为公共对象。使实例变量受保护,并添加一个public get()方法

编辑:这段代码对我来说很好:

#include <map>
#include <iostream>
using namespace std;

template<typename T>
class Component
{
public:
        typedef map<long, T*> pinstances_map;
        pinstances_map instances;

        T * add(long id)
        {
                T *t = new T();
                instances[id] = t;
                return t;
        }
};

struct UnitInfo 
{
        float x, y;
};

class LogicComponent: public Component<UnitInfo> {};

int main()
{
        LogicComponent comp;
        UnitInfo *info = comp.add(99);
        info->x = 10.0;
        info->y = 11.0;

        UnitInfo *info2 = comp.instances[99];
        cout << info2->x << " " << info2->y;

        return 0;
}
#包括
#包括
使用名称空间std;
模板
类组件
{
公众:
typedef映射pinstances\u映射;
pinstances\u映射实例;
T*添加(长id)
{
T*T=新的T();
实例[id]=t;
返回t;
}
};
结构单元信息
{
浮动x,y;
};
类LogicComponent:公共组件{};
int main()
{
逻辑元件组件;
UnitInfo*info=comp.add(99);
信息->x=10.0;
信息->y=11.0;
UnitInfo*info2=组件实例[99];

这段代码本身就有问题:不要动态创建
t
。没有理由这样做,正如现在编写的那样,您泄漏了该对象。至于您看到的问题,您需要发布
EntityID
的小于运算符实现,以及如何调用
运算符[]
在地图上(即,如何创建传递给
操作符[]
?)的id。EntityID只是定义为
typedef unsigned long EntityID;
。我尝试更改代码,但仍然会遇到同样的问题。我是否应该像这样检索实例:
UnitInfo=logic\u c.instances[id];
?@sharvey不,
unitinfo
是一个新实例,
unitinfo&info
是对现有实例的引用。如果您来自Java,您可能需要阅读以下内容:我确实来自Java背景。奇怪的是,当我在更改它之后立即访问它时,值是正确的;但当我稍后再次获得它时,tX的值仍然是0。我会更新这个问题。谢谢。谢谢,我现在明白为什么C++ FAQ Lite说你可能不需要在C++中使用指针。我不认为它也会应用到这样的事情。我正在访问实例子字段,所以我没有[]。组件模板上调用了运算符。当然,我可能错了。我将绝对实现运算符[]就像你建议的,因为它更好。谢谢。你所描述的正是我想要实现的。切换到你所描述的是我想我尝试过的,但是当在你最后一行之后调用info->x时,我得到了一个EXC\u BAD\u访问,信息指向0x0。我同意,这段代码是有效的。当我尝试从代码的另一部分访问它时(渲染函数传递给
glutDisplayFunc
glutIdleFunct
,指针仍然指向0x0。您正在访问同一个LogicComp对象吗?不,我没有。我有一个类成员存储定义为
LogicComponent logic\u c;
的LogicComponent。将其更改为
LogicComponent&logic\u c;
修复了它!谢谢太多了。
typedef std::map<EntityID, T*> pinstances_map;

T * add(EntityID id) {
    T* t = new T();
    instances[id] = t;
    return t;
};  

// initialize as 
UnitInfo *info = comp.add(id);
info->x = 10.0;
info->y = 11.0;

// retrieve as 
UnitInfos *info = comp.instances[id];
#include <map>
#include <iostream>
using namespace std;

template<typename T>
class Component
{
public:
        typedef map<long, T*> pinstances_map;
        pinstances_map instances;

        T * add(long id)
        {
                T *t = new T();
                instances[id] = t;
                return t;
        }
};

struct UnitInfo 
{
        float x, y;
};

class LogicComponent: public Component<UnitInfo> {};

int main()
{
        LogicComponent comp;
        UnitInfo *info = comp.add(99);
        info->x = 10.0;
        info->y = 11.0;

        UnitInfo *info2 = comp.instances[99];
        cout << info2->x << " " << info2->y;

        return 0;
}