问题
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