调用静态函数时c ++ globlal / stack实例ctor / dtor崩溃

时间:2013-03-06 08:25:14

标签: c++ static-members

我在main的同一个文件中定义了一个类,在另外两个单独的文件中定义了另一个类(充满静态函数/成员),它崩溃了。我想这可能与全局/静态实例的生命周期有关。似乎在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中,它不会崩溃,但是这些代码不会生成相同的代码吗?

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

1 个答案:

答案 0 :(得分:7)

问题在于你不知道将构造全局变量的顺序是什么:

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

这个

//main.cpp
Nc nc;

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

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

nc

然后保证订单。这是宣言的顺序。所以,只要你先放//main.cpp std::map<int, int> Sc::map_; Nc nc; ,它就会全部有效。

有一种简单的方法来解决这个问题:

替换它:

Sc::map_

使用:

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

但真正的问题是你正在使用全局可变状态(全局变量)。尽量不要使用它们。它将您的代码紧密绑定到globl状态。您应该将状态传递给带参数的方法或通过知道如何检索状态的对象。