初始化地图被报告为空的奇怪行为

Strange behaviour where initialised map being reported as empty

我有以下三个文件:

test.h

#pragma once
#include <iostream>

class Test{
public:
    Test(std::string string);
};

test.cpp

#include "test.h"
#include <map>

std::map<int, int> HEY = {
    {1, 45},
    {2, 2}
};


Test::Test(std::string string)  {
    std::cout << "hello" << std::endl;
    if (HEY.empty()) {
        std::cout << "Is empty!" << std::endl;
    } else {
        std::cout << "Not empty!" << std::endl;
    }
}

Source.cpp

#include "test.h"

Test test("hey");


int main() {

    return 0;
}

预期输出

hello
Not empty!

实际输出

hello
Is empty!

当我 运行 Microsoft Visual Studio 2019 中的程序时,我期望“不为空!”被输出,表明映射 HEY 中有元素,因为它是用两对初始化的。但是输出实际上是“是空的!”。

我不想在 main 函数中初始化 test,因为我希望它是一个全局变量,尽管我注意到当我在 main 函数中创建它时我得到了正确的输出。

我做错了什么?这是 compiler/linker 错误吗?我没有适当地声明 HEY 地图吗?重要的是 test 仍然是一个全局变量。

您的 HEYtest 对象都在程序启动时在调用 main() 之前在全局内存中创建。 test 对象只是首先被创建,这就是为什么当 test 的构造函数是 运行 时 map 仍然是空的(从技术上讲,map '甚至尚未创建)。参见 Static Initialization Order Fiasco

test 对象的创建移动到 main() 中,您应该会看到您期望的输出。否则,您将不得不将 HEY 的初始化延迟到 test 之后,例如将 HEY 包装在一个单例中,该单例在第一次使用时对其进行初始化,例如:

#include "test.h"
#include <map>

struct MapSingleton {
    static std::map<int, int>& Get() {
        static std::map<int, int> HEY = {
            {1, 45},
            {2, 2}
        };
        return HEY;
    }
};

Test::Test(std::string string)  {
    std::cout << "hello" << std::endl;
    if (MapSingleton::Get().empty()) {
        std::cout << "Is empty!" << std::endl;
    } else {
        std::cout << "Not empty!" << std::endl;
    }
}