为什么在退出循环后,std::multimap 的元素会发生变化?

huangapple go评论70阅读模式
英文:

Why are the elements of the std::multimap changing after exiting the loop in this code?

问题

I am trying to implement a transparency in my OpenGL program. Currently I have such function (minimal reproducible example):

#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;
}

After running this code, I get the following result:

1 1 0

The first two numbers are 1, but the third number for some reason is 0, not 1. I tried to use the debugger, but it did not help. What is my mistake here?

英文:

I am trying to implement a transparency in my OpenGL prorgam. Currently I have such function (minimal reproducible example):

#include &lt;map&gt;
#include &lt;unordered_map&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;

class Sprite
{
public:
    std::vector&lt;int&gt; m_meshes;
    std::pair&lt;float, float&gt; pos;
};

int main()
{
    std::unordered_map&lt;int, Sprite&gt; m_sprites = {
        { 0, { { 43 } } },
        { 1, { { 234 } } }
    };

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

    return 0;
}

After running of this code, I get the following result:

1 1 0

The first two numbers are 1, but the third number for some reason is 0, not 1. I tried to use debugger, but it did not help. What is my mistake here?

答案1

得分: 5

const std::pair&lt;int, Sprite&gt;&amp; spritePair超出范围(在每次迭代中),Sprite副本 将消失,指针将悬空。

您可以通过将其修改为

const std::pair&lt;const int, Sprite&gt;&amp; spritePair

来修复它,这样将引用映射中的实际 pair,而不是通过转换创建 std::pair&lt;int, Sprite&gt;

另一种替代方法是使用结构化绑定:

for (const auto&amp; [idx, sprite] : m_sprites) {
    translucentSprites.insert({sprite.pos.first + sprite.pos.second, &amp;sprite});

一个简化方法是使用 emplace 而不是 insert

translucentSprites.emplace(sprite.pos.first + sprite.pos.second, &amp;sprite);
英文:

When const std::pair&lt;int, Sprite&gt;&amp; spritePair goes out of scope (in each iteration), the copy of the Sprite will be gone and the pointer will be dangling.

You can fix it by making it

const std::pair&lt;const int, Sprite&gt;&amp; spritePair

which would then reference the actual pair in the map instead of creating a std::pair&lt;int, Sprite&gt; via conversion.

An alternative fix is to use structured bindings:

for (const auto&amp; [idx, sprite] : m_sprites) {
    translucentSprites.insert({sprite.pos.first + sprite.pos.second, &amp;sprite});

A simplification could be to use emplace instead of insert:

translucentSprites.emplace(sprite.pos.first + sprite.pos.second, &amp;sprite);

huangapple
  • 本文由 发表于 2023年6月8日 20:25:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76431849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定