Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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 prorgam. 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 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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

When const std::pair<int, Sprite>& 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<const int, Sprite>& spritePair

which would then reference the actual pair in the map instead of creating a std::pair<int, Sprite> via conversion.

An alternative fix is to use structured bindings:

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

A simplification could be to use emplace instead of insert:

translucentSprites.emplace(sprite.pos.first + sprite.pos.second, &sprite);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading