std::map 包含最后一个实例的值,然后才被告知存储该值

std::map contains value from last instance before it's told to store said value

所以最近我在试验一些代码时发现了一个非常奇怪的错误。我创建了一个 std::map 来为我的程序存储字体。然而,通过长时间的调试,我设法发现在我将 "arial" 放入其中之前,该映射存储了一个带有键 "arial" 的值 (NULL)。所以我还发现,当我更改程序使其永远不会在地图中放置 "arial" 时,地图仍然包含 "arial".

这是我设置的 class 层次结构的基本再现:

#include "SDL_ttf.h"
#include <map>
#include <string>
#include <array>

class AssetManager{
public:
    void addFont(std::string ID, std::string path, int fontSize){
        std::cout <<""; //if we put a breakpoint here, the first time it stops, "arial" is already defined within fonts.
        fonts.emplace(ID, TTF_OpenFont(path, fontSize);
    }
private:
std::map<std::string, TTF_Font*> fonts;
};

class Game{
public:

void init(){
    if(TTF_Init() == -1){
    std::cout << "Failed to init SDL_TTF" << std::endl; //this has never gotten called; TTF always succeeds in initializing
    }
    assets->addFont("fontname", "assets/Arial.ttf", 16);
}

static shared_ptr<AssetManager>(new AssetManager) assets;

};

main(int argc, char* argv[]){
    Game *game = nullptr;
    game = new Game;
    game->init();
}

如您所见,在该程序中,我们从未添加名为 "arial" 的字体,但出于某种原因(我假设是缓存错误),字体包含数据对于 "arial" 之前,在程序的这个实例中,"arial" 是什么。换句话说,"arial" 是在前一个实例中定义的,但从未在这个实例中定义过,但是映射仍然有一个键 "arial"。如果有人知道为什么或如何发生这样的事情,我很想听听。

我猜你正在使用 std::maps operator[]。 该操作员不仅会查找现有条目。它将 创建 如果条目不存在,则使用默认构造(实际上 "value initialized")值。

这其实在很多情况下都是一个特性。例如,它允许您执行类似以下操作来计算字符串中字符的出现次数:

std::map<char, int> result;
for (const auto& c : some_string) {
    ++result[c];
}

如果您只想查找一个键,没有插入行为,那么您有几个选择:

std::map::at

std::map::find

std::map::contains

others.