2

我在 main 的同一个文件中定义了一个类,在 2 个单独的文件中定义了另一个类(充满静态函数/成员),它崩溃了。我想这可能与全局/静态实例的生命周期有关。似乎在ctor中,静态成员尚未初始化,并且可能会在退出时,在第一个实例被破坏之前释放静态成员。这是测试代码:

    //testh.h
    #include <map>
    class Sc {
    public:
        static void insert();
        static void out();

    private:
        static std::map<int, int> map_;
    };

    //testcpp.cpp
    #include "testh.h"
    #include <iostream>
    std::map<int, int> Sc::map_;

    void Sc::insert() {
        map_.insert(std::make_pair(2,3));
    }

    void Sc::out() {
        for(auto m : map_) {
            std::cout << m.first << ' ' << m.second << '\n';
        }
    }

    //main.cpp
    #include "testh.h"
    class Nc {
    public:
        Nc() {
            Sc::insert();
            Sc::out();
        }
        ~Nc() {
            Sc::insert();
            Sc::out();
        }
    };

    Nc nc;
    int main() {

        system("pause");
        return 0;
    }

以下是上述代码的一些奇怪行为:

如果我将 staic 成员替换为 int,它不会崩溃,所以我想 std::map 可能有问题?

如果我将所有代码放入 main.cpp,它不会崩溃,但是这些代码不会生成相同的代码吗?

如果我不想进行动态分配(新),如何解决这个问题?

4

1 回答 1

8

问题是您不知道全局变量的构造顺序:

// test.cpp
std::map<int, int> Sc::map_;

还有这个

//main.cpp
Nc nc;

因为它们在不同的编译单元中,所以标准不保证它们将被创建的顺序。因此,如果nc首先创建它们,那么任何使用尝试Sc::map_都会失败(并且nc确实通过它对静态的调用来使用它)。

当您将全局变量放入一个文件时:

//main.cpp
std::map<int, int> Sc::map_;
Nc nc;

然后保证订单。这是声明的顺序。所以只要你把Sc::map_它放在第一位,那么一切都会奏效。

有一个简单的技术可以解决这个问题::

替换这个:

private:
    static std::map<int, int> map_;
};

和:

private:
    static std::map<int, int>& getMap()
    {
        static std::map<int, int> instance;
        return instance;
    }
};

But the real problem is that you are using global mutable state (global variables). Try not to use them at all. It tightly binds your code to the globl state. You should be passing state to methods with parameters or via objects that know how to retrieve the state.

于 2013-03-06T08:34:04.287 回答