C++静态变量的初始化(再一次)

标签 c++ variables static initialization

如果我在不同的编译单元中有两个静态变量,那么它们的初始化顺序是没有定义的。这个教训很好学。

我的问题是:当第一个静态变量被初始化时,所有的静态变量都已经分配了吗?换句话说:

static A global_a; // in compilation unit 1
static B global_b; // in compilation unit 2

struct A {
    A() { b_ptr = &global_b; }
    B *b_ptr;

    void f() { b_ptr->do_something(); }
}

int main() {
    global_a.f();
}

b_ptr 会指向一 block 有效的内存,在执行 main 函数时分配和初始化 B 吗?在所有平台上?

长话短说:

编译单元1是Qt库。 另一个是我的应用程序。我有几个 QObject 派生类,我需要能够通过类名字符串实例化。为此,我想出了一个模板化的工厂类:

class AbstractFactory {
public:
    virtual QObject *create() = 0;
    static QMap<const QMetaObject *, AbstractFactory *> m_Map;
}
QMap<const QMetaObject *, AbstractFactory *> AbstractFactory::m_Map; //in .cpp

template <class T>
class ConcreteFactory: public AbstractFactory {
public:   
    ConcreteFactory() { AbstractFactory::m_Map[&T::staticMetaObject] = this; }
    QObject *create() { return new T(); }
}

#define FACTORY(TYPE) static ConcreteFactory < TYPE > m_Factory;

然后我在每个 QObject 子类定义上添加这个宏:

class Subclass : public QObject {
   Q_OBJECT;
   FACTORY(Subclass);
}

最后我可以通过类型名实例化一个类:

QObject *create(const QString &type) {
    foreach (const QMetaObect *meta, AbstractFactory::m_Map.keys() {
        if (meta->className() == type) {
           return AbstractFactory::m_Map[meta]->create();
        }
    }
    return 0;
}

所以这个类得到一个静态的QMetaObject实例:Subclass::staticMetaObject来自 Qt 库 - 它在 Q_OBJECT 中自动生成我认为宏。然后是 FACTORY宏创建静态 ConcreteFactory< Subclass >实例。 ConcreteFactory 在其构造函数中尝试引用 Subclass::staticMetaObject。

我对 linux (gcc) 上的这个实现非常满意,直到我用 Visual Studio 2008 编译它。出于某种原因,AbstractFactory::m_Map 在运行时为空,并且调试器不会在工厂构造函数处中断。

所以这就是引用其他静态变量的静态变量的味道的来源。

我如何优化此代码以避免所有这些陷阱?

最佳答案

是的,标准允许这样做。

[basic.life] 部分中有许多段落开始

Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways.

并且有一个脚注表明这特别适用于您的情况

For example, before the construction of a global object of non-POD class type

关于C++静态变量的初始化(再一次),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4379337/

相关文章:

c++ - 指针在使用前必须先初始化,那么char *p怎么理解?

c++ - 在纯 DOS 模式下写入文件?

c++ - 跳出内部循环并不会终止循环

javascript - 当另一个变量变为 false 时覆盖一个变量 Angular.js

rust - Rust lazy_static变量RwLock访问

c++ - 在 Raspberry 上使用 C++ 创建 RRD 文件时行为异常

c++ - 使用字符串变量将短语分配给数字? C++

c++ - 全局和局部变量

python - 如何将 .swf 文件嵌入到我的 Google App Engine 应用程序中?

css - Django 静态文件未加载。修复 settings.py 以加载相对路径上的文件