【问题标题】:Two size() calls to the same object returning different values对同一对象的两次 size() 调用返回不同的值
【发布时间】:2016-07-09 00:23:56
【问题描述】:

我有一个函数可以将一个值插入到一个向量映射的空映射中。 (该特定结构可以满足我对渲染对象进行一些复杂排序的需求)。

但是,当我向其中添加内容时,我的数据似乎在结构中的某个位置丢失了。

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

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 语句的底部附近。理论上它们应该指向同一个对象,但第一次调用返回的值与第二次不同。

只是我的代码有问题,还是我从根本上误解了迭代器的工作原理?

【问题讨论】:

  • 你为什么不对map::insert的返回值测试.second

标签: c++ dictionary iterator


【解决方案1】:
std::map<float, std::vector<GameObjectPtr>> objectMapping = objectLocation->second;

这会将objectLocation-&gt;second 复制到名为objectMapping 的新地图中。 objectMapping 是一个新对象,它是从 objectLocation-&gt;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;

【讨论】:

  • 在过去的几年里,我做的 Objective-C 比 Java 还多,所以我真的不知道我以前怎么没遇到过。我的意思是,我很快就想到是这种情况,只是我不知何故不知道使用 & 修复它
  • 仅仅声明“使用并修复它”是不准确的。更准确的说法是“使用参考修复它”。无偿打耳光,任何时候你认为你有同样的问题都不太可能产生有效的结果。了解 C++ 对象的工作原理很重要,其中包括指针、引用和范围的主题。了解整个 C++ 对象模型的工作原理是编写正确代码的关键。
【解决方案2】:

但是你打印的不是同一个东西。

第一个printf 调用打印objectMapping 的大小,即std::map

第二次调用打印来自renderOrderMap向量的大小。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 2014-08-10
    • 2018-03-24
    • 2022-11-29
    • 2016-11-19
    • 1970-01-01
    相关资源
    最近更新 更多