带私有构造函数的C ++单例

时间:2013-09-04 12:18:09

标签: c++ constructor new-operator delete-operator

我需要具有应用程序生命周期的单例,保证创建/销毁和静态访问它。

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

但我不知道如何摆脱g ++警告:

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

如果我编写C *而不是void *,则析构函数开始在无限循环中调用自身。有人可以帮助我在没有警告的情况下获得干净的代码吗?当然是C ++ 98。

4 个答案:

答案 0 :(得分:3)

我习惯写单身的方式(每当我真正需要的时候)是:

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

private:
     Singleton()
     {
     }
};

无需担心重载newdelete

答案 1 :(得分:2)

您既不需要重载new()也不需要delete()。 而且您可能不需要向客户分发指针。参考将做。

单身人士的建造和破坏将在你的instance()中完成,这可能是这样的:

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

这保证了构造和销毁,因为当第一个用户调用instance()时,调用C的构造函数,并且仅在第一次调用时调用。 破坏将在您的计划结束时发生。

答案 2 :(得分:0)

要删除的类型为char*

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

您的新内容中存在错误:What's the difference between new char[10] and new char(10)

也许应该是:

p=new char[sz];

然后

delete[] (char*)p ;

----编辑:

删除纯粹主义者,牺牲了人们学习的清晰度; P:

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

(*实际上我很欣赏有关演员的说明)

答案 3 :(得分:0)

在我看来,如果您只删除newdelete重载(如果您想记录每个con / destruction,我没有真正看到它的重载),那么您的代码应该可以正常工作,在con / destructors中这样做,但下面应该修复你的错误。

由于您将char*分配给p,因此将其投放到删除中的char*应该有效,即delete (char*)p;

但是,我相信p=new char(sz);正在创建一个值为sz的char,而不是一个大小为sz的char数组。对于后者,您可能需要p=new char[sz];,然后delete[] pdelete[] (char*)p;