You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何退出循环后std::multimap中的元素内容发生异常变化?

容器迭代指针悬空导致的未定义行为问题

我正在尝试在OpenGL程序中实现透明效果,以下是最小可复现示例代码:

#include <map>
#include <unordered_map>
#include <iostream>
#include <vector>

class Sprite
{
public:
    std::vector<int> m_meshes;
    std::pair<float, float> pos;
};

int main()
{
    std::unordered_map<int, Sprite> m_sprites = {
        { 0, { { 43 } } },
        { 1, { { 234 } } }
    };

    std::multimap<int, const Sprite*, std::greater<int>> translucentSprites{};
    for (const std::pair<int, Sprite>& spritePair : m_sprites)
    {
        translucentSprites.insert({ spritePair.second.pos.first + spritePair.second.pos.second, &spritePair.second});
        std::cout << translucentSprites.begin()->second->m_meshes.size() << ' ';
    }
    std::cout << translucentSprites.begin()->second->m_meshes.size() << '\n';

    return 0;
}

运行该代码后,输出结果为:

1 1 0

前两个输出值为1,但第三个值却为0而非1。我尝试使用调试器排查但未找到问题根源,请问我的代码存在什么错误?


错误根源

问题出在循环迭代时的类型不匹配导致的临时对象与悬空指针:

std::unordered_map<int, Sprite>的元素类型是std::pair<const int, Sprite>,但你在for循环中用const std::pair<int, Sprite>&去接收元素。这种类型不匹配会让编译器自动创建一个临时的std::pair<int, Sprite>对象,spritePair引用的是这个临时对象,而非m_sprites容器里的真实元素。

每次循环迭代结束后,这个临时对象就会被销毁。你插入到translucentSprites中的&spritePair.second是临时对象的地址,循环结束后这些指针全部变成了悬空指针。访问悬空指针指向的内存属于未定义行为,第三个输出的0就是这种行为的随机结果。

修复方法

将循环中的迭代类型改为const std::pair<const int, Sprite>&,或者直接用auto&让编译器自动推导正确的类型,这样就能直接引用容器内的真实元素,避免临时对象的生成:

for (const auto& spritePair : m_sprites)
{
    translucentSprites.insert({ spritePair.second.pos.first + spritePair.second.pos.second, &spritePair.second});
    std::cout << translucentSprites.begin()->second->m_meshes.size() << ' ';
}

修改后运行代码,输出会变为1 1 1,符合预期。


内容的提问来源于stack exchange,提问作者Roman Leshchuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:43:08