8

标题基本上说明了一切,我想知道 C++ 类的静态成员何时初始化以及何时超出范围。

我需要这个来解决以下问题。我有许多类 Foo 的对象,每个对象都需要访问由另一个类 Bar 封装的资源。同步不是问题,所以我希望所有对象共享同一个 Bar 实例。

我正在使用一个简单的托管指针进行引用计数。

我可以执行以下操作:

class Foo {
private:
    static managed_pointer<Bar> staticBar;
public:
    Foo() {
        if(!staticBar)
            staticBar = new Bar;
    }
    /*
     * use staticBar in various non-static member functions
     */
};

managed_pointer<Bar> Foo::staticBar = NULL;

managed_pointer staticBar 应该在 Bar 对象超出范围后立即删除它 - 但是什么时候会发生这种情况?当 Foo 的最后一个实例被破坏时?在应用程序退出?

谢谢你的建议!

4

3 回答 3

13

statics 和 globals 在程序启动之前初始化(在main被调用之前,程序实际上在此之前启动)并在退出后超出范围main

例外 - 局部静态(在函数内部声明的静态变量)和未使用的模板类static成员。

它与实例的数量无关。

于 2012-07-04T13:26:38.493 回答
2

该标准没有指定精确的初始化顺序,它是特定于实现的。它们将在程序开始时被实例化并在结束时被释放。

你必须非常小心你正在做的事情,因为如果你有一些其他依赖这个对象存在的静态对象,那就是 UB。不知道它们将以什么顺序被初始化。

您可能会查看 boost::call_once 之类的东西以确保它被初始化一次,但我不会依赖于静态初始化的顺序。

据我所知,你的代码可以工作,但我之前一直被静态初始化问题所困扰,所以我想警告你。

编辑:同样在您的代码中,当 managed_ptr 超出范围(程序结束)时,它将自动删除分配的内存。但是您不应该在 Bar 的析构函数中做任何不重要的事情,因为您可能会通过调用其他释放的实例甚至已删除的代码来触发 UB(就像我曾经在删除动态库时发生的那样)。基本上你是在一个雷区,所以要小心。

于 2012-07-04T13:29:44.130 回答
1

The first thing that pops out of your question is the common misconception that scope and lifetime are equivalent concepts. They are not. In some cases as with local variables, the lifetime is bound to a particular context, but that is not always the case.

A class static member variable has class scope (it is accessible anywhere in the program) and static lifetime, which means that it will be initialized in order with respect to the other static variables in the same translation unit, and in an undefined order with respect to other static variables in other translation units, before main (caveat: initialization need not be performed before the first statement in main, but it is guaranteed to be before the first odr-use of the variable).

于 2012-07-04T14:55:05.370 回答