两个size()调用同一个对象返回不同的值

时间:2016-07-09 00:23:57

标签: c++ dictionary iterator

我有一个函数,用于将值插入到向量映射的空映射中。 (该特定结构适用于我对渲染对象的一些复杂排序的需要)。

然而,当我向其中添加内容时,我的数据似乎在结构的某个点上丢失了。

我的方法代码(带有一点上下文)在这里:

typedef unsigned int ComponentUID;

//For the purposes of this example, assume the map is completely empty
std::map<ComponentUID, std::map<float, std::vector<GameObjectPtr>>> renderOrderMap;

void Render::addGameObjectToMap(GameObjectPtr objectPtr) {

    //Expose the pointer for ease of use
    GameObject *object = objectPtr.get();

    //Set up component local variables
    RenderComponent *component = object->getRenderComponent();
    ComponentUID uid = component->getComponentUID();

    //Get object's render level (arbitrary float)
    float renderLevel = object->getRenderLevel();

    //Find the location of the component UID in the render order map
    std::map<ComponentUID, std::map<float, std::vector<GameObjectPtr>>>::iterator objectLocation = renderOrderMap.find(uid);

    //If the object doesn't exist in the map
    if (objectLocation == renderOrderMap.end()) {

        //Add a new pair with the component UID and a fresh float/vector map and set the object location to the iterator pointing to it
        objectLocation = renderOrderMap.insert(std::pair<ComponentUID, std::map<float, std::vector<GameObjectPtr>>>(uid, std::map<float, std::vector<GameObjectPtr>>())).first;

        printf("Inserted pair");
    }

    //Get the map at the value of the object location iterator
    std::map<float, std::vector<GameObjectPtr>> objectMapping = objectLocation->second;

    //Find the render level in the map
    std::map<float, std::vector<GameObjectPtr>>::iterator vectorLocation = objectMapping.find(renderLevel);

    //If the object doesn't exist in the map
    if (vectorLocation == objectMapping.end()) {

        //Add a new pair with the render level and a fresh GameObjectPtr vector and set the vector location to the pair's iterator 
        vectorLocation = objectMapping.insert(std::pair<float, std::vector<GameObjectPtr>>(renderLevel, std::vector<GameObjectPtr>())).first;

        /*
        *  These two should equal the same value, because they should call the same method on the same object
        */
        printf("Mapping size: %i", objectMapping.size());   //Outputs 1
        printf("ExtraMapSize0: %i", renderOrderMap.find(uid)->second.size());   //Outputs 0
    }

    //Add the game object to the vector
    std::vector<GameObjectPtr> objectVector = vectorLocation->second;
    objectVector.push_back(objectPtr);

}

问题在于底部有两个printf语句。从理论上讲,它们应指向同一个对象,但第一个调用会向第二个调用返回不同的值。

我的代码是否存在问题,或者我是否从根本上误解了迭代器的工作方式?

2 个答案:

答案 0 :(得分:1)

std::map<float, std::vector<GameObjectPtr>> objectMapping = objectLocation->second;

这会将objectLocation->second复制到名为objectMapping的新地图中。 objectMapping是一个新对象,由objectLocation->second复制构建。

    vectorLocation = objectMapping.insert(...

这会在objectMapping对象中插入一个新值。

    /*
    *  These two should equal the same value, because they should call the same method on the same object
    */
    printf("Mapping size: %i", objectMapping.size());   //Outputs 1
    printf("ExtraMapSize0: %i", renderOrderMap.find(uid)->second.size());   //Outputs 0

不,他们不是同一个对象。它们是不同的对象。这不是调用相同对象的相同方法,而是调用两个不同的独立对象的相同方法。这就是为什么你没有得到相同的价值。

我猜你最初是一名Java开发人员,而你现在正在学习C ++。这就是对象在Java中的工作方式,但它们在C ++中的工作方式不同。您声明了一个名为objectMapping的新对象,从另一个对象复制构造它,另一个映射中的值。

如果你真的希望它们是同一个对象,你必须使objectMapping成为参考。

std::map<float, std::vector<GameObjectPtr>> &objectMapping = objectLocation->second;

答案 1 :(得分:0)

但你不打印同样的东西。

第一个printf来电打印的objectMapping大小为std::map

第二个调用从renderOrderMap打印向量的大小。