【问题标题】:Strange behaviour where initialised map being reported as empty初始化地图被报告为空的奇怪行为
【发布时间】:2020-11-25 18:41:03
【问题描述】:

我有以下三个文件:

测试.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;
    }
}

来源.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 函数中创建它时,我得到了正确的输出。

我做错了什么?这是编译器/链接器错误吗?我没有适当地声明HEY 地图吗? test 必须是一个全局变量。

【问题讨论】:

标签: c++ class visual-studio-2019 stdmap


【解决方案1】:

您的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;
    }
}

【讨论】:

  • 感谢您提供的信息和示例!真的帮了大忙!
  • 这些 Singleton 对象的命名约定是什么?一个单例会容纳多个 Get() 函数,还是更喜欢将它们保存在单独的单例对象中?
  • @Tom 使用您想要的任何对您有意义的命名约定。最终编译的可执行文件中不存在名称。无论您使用 1 个单例还是多个,这完全取决于您。
猜你喜欢
  • 2021-12-06
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多