C ++ Initializing Static Variables (Once Again)

If I have two static variables in different compilation units, then their initialization order is not defined. This lesson has been well studied.

The question I have is: all static variables already allocated when the first is initialized. In other words:

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();
}

Will b_ptr point to the real part of memory where B is allocated and initialized during the execution of the main function? On all platforms?

Longer story:

Compilation unit 1 is a Qt library. Another is my application. I have a couple of classes based on QObject that I need to instantiate using the class name string. For this, I came up with a boilerplate factory class:

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;

Then I add this macro to each QObject subclass definition:

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 :: staticMetaObject.

linux (gcc), Visual Studio 2008. - AbstractFactory:: m_Map , factory .

, .

, ?

+5
5

, .

[basic.life] ,

, , , , , , , .

, , .

, -POD

+5

: , . . Ben Voigt

:

- :
, , , ( ). , ( ).

, , , , , ( ).

struct A
{
    // Rather than an explicit global use
    // a static method thus creation of the value is on first use
    // and not at all if you don't want it.
    static A& getGlobalA()
    {
        static A instance;  // created on first use (destroyed on application exit)
     // ^^^^^^ Note the use of static here.
        return instance;    // return a reference.
    }
  private:
    A() 
        :b_ref(B::getGlobalB())     // Do the same for B
    {}                              // If B has not been created it will be
                                    // created by this call, thus guaranteeing
                                    // it is available for use by this object
    }
    B&  b_ref;
  public:
    void f() { b_ref.do_something(); }
};

int main() {
    a::getGlobalA().f();
}

.

  • - .
  • , , - ( /).
+2

. .data, ( ).

-: , , , , .

+1

B , A, , , undefined. , , . B - , . .

+1

, , " ", . , . , . . global_a.b_ptr , NULL, _b. , , undefined, , ( C):

// unit 1
int a = b + 1;

// unit 2
int b = a + 1;

main ... printf("%d\n", a + b); // 3 for sure

:

int get_x() {
  static int init;
  static int x;
  if(init) return x;
  else { x = some_calc(); init = 1; return x; }
}

- , .

+1

All Articles