C++ singleton with private constructor

徘徊边缘 提交于 2019-12-11 07:23:53

问题


I need singleton with a application lifetime, guaranteed creation/destruction and static access to it.

#include <iostream>
#include <cstdlib>

#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&);             \
    void operator=(const TypeName&)

#define M() C::sM()
#define M2() C::sM2()

using namespace std;

class C {
  private:
    static C* s;

    ~C() { cout << "~C()" << endl; }
    static C* instance() { 
        if (s==NULL) { s=new C(); }
        cout << "instance()=" << s << endl; return s; 
    }
    static void cleanUp() { delete s; }
    void m() { cout << "m()" << endl; }
    void m2() { cout << "m2()" << endl; }
    DISALLOW_COPY_AND_ASSIGN(C);
  public:
    C() { 
        cout << "C()" << endl; if (s==NULL) { 
            s=this; atexit(&cleanUp); 
            cout << "cleanUp is installed" << endl; 
        } else { 
            cout << "cleanUp is not installed" << endl; 
        } 
    }
    void* operator new(size_t sz) { 
        void* p=NULL; if (s==NULL) { p=new char[sz]; } else { p=s; }
        cout << "new(" << sz << ")=" << p << endl;
        return p;
    }
    void operator delete(void* p, size_t sz) { 
        cout << "delete(" << sz << "," << p << ")" << endl;
        if (p) delete[] static_cast<char*>(p); s=NULL; 
    }
    void static sM() { cout << "sM()" << endl; instance()->m(); }
    void static sM2() { cout << "sM2()" << endl; instance()->m2(); }
};

C* C::s = NULL;

int main() {
    M();
    M2();
    C* p1 = new C();
    C* p2 = new C();
}  

But I don't know how to get rid of g++ warning:

test.cpp: In static member function 'static void C::operator delete(void*, size_t)':
test.cpp:22: warning: deleting 'void*' is undefined

If I write C* instead of void*, destructor start calling itself in infinite loop. Can anybody help me to get clean code without warnings? C++98 of course.


回答1:


The type to delete is char*:

void operator delete(void* p, size_t sz) { 
    cout << "delete(" << sz << "," << p << ")" << endl;
    if (p) delete (char*) p;
}

There is a bug in your new: What's the difference between new char[10] and new char(10)

Maybe should be:

p=new char[sz];

and then

delete[] (char*)p ;

---- edited:

The delete for purists, sacrificing clarity to people learning ;P :

delete[] static_cast<char*>(p) ;

(*actually I appreciate the note about the cast)




回答2:


The way I'm used to write singletons (whenever I really need one) is:

class Singleton
{
public:
     static Singleton& instance()
     {
          static Singleton theInstance;
          return theInstance;
     }

private:
     Singleton()
     {
     }
};

No need to mess around with overloading new and delete.




回答3:


You do not need to overload neither new() nor delete(). And you probably do not need to hand out a pointer to your customers. A reference will do.

Construction and destruction of the singleton will be done in your instance(), which could look like so:

static C& instance() {
  static C _instance;
  cout << "instance()" << endl; 
  return _instance; 
}

This guarantees construction and destruction, because the constructor of C is called when the first user calls instance(), and only with the first call. Destruction will happen at the end of your program.




回答4:


It looks to me like your code should work if you just remove the new and delete overloads (which I don't really see the point of, if you want to log every con/destruction, do so in the con/destructors), but the below should fix your error.

Since you assign a char* to p, casting it to char* in the delete should work, i.e. delete (char*)p;.

However, I believe p=new char(sz); is making a char with a value of sz instead of a char array of size sz. For the latter, you may want p=new char[sz]; and then delete[] p or delete[] (char*)p;.



来源:https://stackoverflow.com/questions/18613633/c-singleton-with-private-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!