ak.*_*ak. 5 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();
}
Run Code Online (Sandbox Code Playgroud)
b_ptr是否指向一个有效的内存块,其中B是在执行main函数时分配和初始化的?在所有平台上?
更长的故事:
编译单元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;
Run Code Online (Sandbox Code Playgroud)
然后我在每个QObject子类定义上添加这个宏:
class Subclass : public QObject {
Q_OBJECT;
FACTORY(Subclass);
}
Run Code Online (Sandbox Code Playgroud)
最后,我可以通过类型名称实例化一个类:
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;
}
Run Code Online (Sandbox Code Playgroud)
所以这个类得到一个静态QMetaObject
实例:Subclass::staticMetaObject
从Qt库 - Q_OBJECT
我认为它是在宏中自动生成的.然后FACTORY
宏创建一个静态ConcreteFactory< Subclass >
实例.其构造函数中的ConcreteFactory尝试引用Subclass :: staticMetaObject.
我对linux(gcc)上的这个实现非常满意,直到我用Visual Studio 2008编译它.由于某种原因,AbstractFactory :: m_Map在运行时是空的,并且调试器不会在工厂构造函数中断.
所以这就是引用其他静态变量的静态变量气味的来源.
如何优化此代码以避免所有这些陷阱?
是的,标准允许这样做.
部分中有许多段落[basic.life]
开头
在对象的生命周期开始之前但是在对象将占用的存储之后,或者在对象的生命周期结束之后以及在重用或释放对象占用的存储之前,任何指向存储的指针之前可以使用对象将位于或位于的位置,但仅限于有限的方式.
并且有一个脚注表明这特别适用于您的情况
例如,在构造非POD类类型的全局对象之前