Search code examples
c++static-variables

Is it ok to use a static variable to initialize/register variables?


Language: C++ Toolkit: Qt4

The toolkit I'm using has a static method called int QEvent::registerEventType() to register my own event types. When I subclass this QEvent I need to supply the base class this value. QEvent::QEvent(int type).

Is it ok to use a static variable to call this before application starts? Consider the following:

//This is all in my .cpp file

static int myEventType;  //This will contain my registered type

/*If I create a static instance of this class the constructor 
  gets called before the main() function starts.
*/
class DoRegisterMyEventType {  
public:
  DoRegisterMyEventType() {
    myEventType = QEvent::registerEventType();
  }
};

static DoRegisterMyEventType doRegisterMyEventType;

//Here is the constructor for MyEvent class which inherits QEvent.
MyEvent::MyEvent()
  : QEvent(myEventType)
{
}

How 'evil' is this? I could wrap the whole thing in a namespace to prevent polluting the global namespace.


Solution

  • Static level initialization is a huge compiler-dependent grey area, as others have mentioned. However, function level initialization is not a grey area and can be used to your advantage.

    static inline int GetMyEventType()
    {
        static int sEventType = QEvent::registerEventType();
        return sEventType;
    }
    
    MyEvent::MyEvent()
      : QEvent(GetMyEventType())
    {
    }
    

    This solution has the property that registerEventType is guaranteed to be called before you need your event type even if you construct MyEvent during static initialization, which is good, but it does open you up to thread-safety issues if it's possible for MyEvent to be constructed on multiple threads.

    Here's a thread-safe version, based on boost::call_once:

    #include "boost/thread/once.hpp"
    
    static boost::once_flag sHaveRegistered = BOOST_ONCE_INIT; //This is initialized statically, effectively at compile time.    
    static int sEventType = -1; //-1 is not a valid event
    
    static void DoRegister()
    {
        sEventType = QEvent::registerEventType();
    }
    
    static inline int GetMyEventType()
    {
        boost::call_once(sHaveRegistered, &DoRegister);
        return sEventType;
    }