0

I have a singleton class defined in file x.h

class x
{
 public:
     static x* x_instance;
     static x* create_x_instance
     {
        if(!x_instance)
            x_instance = new x;
        return x_instance;
     }
     void someMemberFunction()
  private:
  x() { //some code}
};

extern x *x_interface;     

In x.cpp I have the following:

x *x::x_instance = 0;
x *x_interface = x::create_x_instance();   

In y.cpp, in the constructor of a another singleton class, I have

x_interface->someMemberFunction();    

I get a seg fault because y gets initialized before x. What is the correct way to solve this? I have read many articles on this, but I am still confused.

user2524261
  • 109
  • 2
  • 10
  • 1
    sorry what's stopping you from calling `create_x_instance` in y.cpp? – EdChum Jun 15 '16 at 11:10
  • The order of initialization is not guaranteed. y also being a singleton class, is initialized before x_interface and hence when y's constructor is being executed, x has not been initialized yet – user2524261 Jun 15 '16 at 11:12
  • But I don't understand why you don't have a pointer to `x` as a member in `y.cpp` and then check if it's null or not and then call `create_x_instance` what's the problem? – EdChum Jun 15 '16 at 11:17
  • 1
    Use `Meyers singleton`. – Arunmu Jun 15 '16 at 11:17
  • x is being used by multiple classes, y being just one of them. – user2524261 Jun 15 '16 at 11:18
  • Again, why aren't all callers using a pointer to `x` and then calling `create_x_instance` if `x` is null? This the usual usage semantic – EdChum Jun 15 '16 at 11:19
  • @EdChum That will be very big change to make given that I have a large number of callers in the entire project – user2524261 Jun 15 '16 at 11:30
  • @Arunmu Can you elaborate please? – user2524261 Jun 15 '16 at 11:30
  • @user2524261 See Richards answer. It uses Meyers singleton which won't have static initialization issues and is perfectly thread safe in C++11 – Arunmu Jun 15 '16 at 11:33
  • This is the idiomatic, static trouble free way to create singleton's: http://stackoverflow.com/a/1008289/3807729 – Galik Jun 15 '16 at 11:57
  • @Galik Lets say it's Meyers singleton. That guy needs lots of credit for coming up with this :) – Arunmu Jun 15 '16 at 12:16

3 Answers3

1

Just to be clear, using a static member of a static function avoids initialization order problems:

class x
{
 public:
     static x* get_instance()
     {
         static x* theInst = new x;
         return theInst;
     }

     void someMemberFunction();
  private:
     x() { //some code}
};

Later code gets x like this:

x* handle = x::get_instance();

The above is minimal, it should be further improved to manage x lifetime. It might be better to just have theImpl be a static x rather than pointer-to-x, and get_instance() return a reference instead of a pointer.

Smeeheey
  • 9,906
  • 23
  • 39
  • To your last sentence. Returning a reference instead of a pointer can swap static initialization order problems for static deinitialization order problems. So I think your other suggestion to manage the lifetime of the pointer is probably more robust in the general case. – Tim Seguine May 04 '18 at 09:12
0

allow the compiler to generate the singleton on first use by initialising it as a static member of a static function.

Additionally, you can go further and give your singleton object value semantics with zero cost while offering may benefits:

class x
{
    struct impl
    {
        void someMemberFunction() {

        }
    };
    static impl& get_impl() {
        static impl _{};
        return _;
    }

public:
    void someMemberFunction()
    {
        return get_impl().someMemberFunction();
    }
};

int main()
{
    auto a = x();
    a.someMemberFunction();

}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • 1
    Shouldn't that be `get_impl()` rather than `impl()` in your `x::someMemberFunction()`? – Smeeheey Jun 15 '16 at 11:28
  • This can cause problems when the static is destroyed. If anything that executes after main accesses the singleton, it can have already been destroyed under circumstances which could be difficult to control for under maintenance. If only trivial stuff can ever happen after main in your codebase then it is no problem. – Tim Seguine May 04 '18 at 09:22
0

Why do you need a x_interface as global or static instance as you can get the instance of class x from anywhere at any time using static method : create_x_instance ?

I think best way to use it in class y is as :

(x::create_x_instance())->someMemberFunction();

Vivek Dhiman
  • 319
  • 1
  • 7