1

I'm learning about game development and SFML with the help of this book, SFML Essentials, which shows how to build an asset manager for handling resources. Here is the code from the book:

AssetManager.h

#ifndef ASSET_MANAGER_H
#define ASSET_MANAGER_H

#include <map>
#include "SFML/Graphics.hpp"

class AssetManager
{
public:
    AssetManager();

    static sf::Texture& GetTexture(std::string const& filename);

private:
    std::map<std::string, sf::Texture> m_Textures;

    // AssetManager is a singleton, so only one instance can exist at a time
    // sInstance holds a static pointer to the single manager instance
    static AssetManager* sInstance;
};

#endif // !ASSET_MANAGER_H

AssetManager.cpp

#include "AssetsManager.h"
#include <assert.h>

AssetManager* AssetManager::sInstance = nullptr;

AssetManager::AssetManager()
{
    // Only allow one AssetManager to exist
    // Otherwise throw an exception
    assert(sInstance == nullptr);
    sInstance = this;
}

sf::Texture& AssetManager::GetTexture(std::string const& filename)
{
    auto& texMap = sInstance->m_Textures;

    // See if the texture is already loaded
    auto pairFound = texMap.find(filename);
    // If loaded, return the texture
    if (pairFound != texMap.end())
    {
        return pairFound->second;
    }
    else // Else, load the texture and return it
    {
        // Create an element in the texture map
        auto& texture = texMap[filename];
        texture.loadFromFile(filename);
        return texture;
    }
}

The author uses a map to cache textures, but wouldn't it be better to use an unordered_map to help improve lookup times? What would be the advantages/disadvantages of each in a full scale game?

gentlemanRabbit
  • 115
  • 1
  • 6
  • 4
    Use `map` when order is important, and strict weak order is deducible. Use `unordered_map` when order is *not* important, and equivalence is deducible directly, not mandated by a strict weak order. The latter often offers better performance if you can live with the restrictions, including providing hashing for custom keying. – WhozCraig Jan 11 '21 at 05:56
  • It can also depend on the cost of hashing vs comparing, but this is rare. One more thing to consider is the issue of bucketing, which can make lookup time poor if you have a very very high number of assets. – Fantastic Mr Fox Jan 11 '21 at 06:02
  • `unordered_map` should be faster. But most likely difference is insignificant compared to other operations that you'll need to do with textures. BTW this is a weird way to make a singleton. – ALX23z Jan 11 '21 at 06:02
  • Another reason that `std::map` might be preferred sometimes is if you happen to be storing pointers into that map's data somewhere else, and allowing the map to be modified (_e.g._ adding new items to the cache / expelling old ones) without invalidating your pointers. – paddy Jan 11 '21 at 07:06
  • 1
    @paddy Neither adding items or deleteing items will invalidate pointers or references to values in an unordered_set. Only iterators get invalidated like this. – john Jan 11 '21 at 07:08
  • Hmm, even after table growth causes a rehash? That's counter-intuitive. I need to go study up the implementation details, cos for years I've been believing that I can't rely on this. This would suggest that the allocator is hit almost as hard as for `std::map`, which would be a bummer. – paddy Jan 11 '21 at 07:14
  • @paddy and @john, sounds like you have a misunderstanding, i think you need to check if you are looking at a `map` or have a pointer to an element in a `map`. You are both correct, its just the situation might be different. – Fantastic Mr Fox Jan 11 '21 at 07:25
  • Please don't add confusion. Neither of us are talking about the contained type being a pointer. – paddy Jan 11 '21 at 07:39

0 Answers0