单例模式
#include<stdio.h> class CSingle2 { public: static CSingle2* getInstance(); void setKey(int k); void printKey(); ~CSingle2(); private: CSingle2();
CSingle2(const CSingle2&);
const CSingle2& operator=(const CSingle2&); static CSingle2 *pSingle2; class Garb { public: ~Garb() { printf("Garb destructor called\n"); if(pSingle2!=NULL) { delete CSingle2::pSingle2; CSingle2::pSingle2 = NULL; } } }; static Garb oGarb; int key; }; CSingle2::Garb CSingle2::oGarb;//必须在类外初始化Garb,才能在结束时自动调用Garb的析构函数 CSingle2* CSingle2::pSingle2=NULL; CSingle2* CSingle2::getInstance() { if(pSingle2 == NULL) { pSingle2 = new CSingle2(); } return pSingle2; } CSingle2::CSingle2()//构造函数必须实现,不能只声明。 { this->key = 0; } CSingle2::~CSingle2()//一般的程序结束是不会调用析构函数的,除非delete getInstance返回的指针,该析构函数中不能delete单例的指针,因为只有直接delete才会调用该析构函数,然后再delete,就进了死循环了。 { printf("CSingle2 destructor called\n"); } void CSingle2::setKey(int k) { key =k; } void CSingle2::printKey() { printf("key:%d\n",key); } int main() { CSingle2 *p1 = CSingle2::getInstance(); p1->setKey(5); CSingle2 *p2 = CSingle2::getInstance(); p2->printKey(); return 0; }
以上是懒汉模式,即只有第一次调用getInstance时才会初始化实例。但是,它并不是多线程安全的,因为一个线程判断没有初始化过该实例后,可能切到了另一个线程判断有没有实例化过,这样就会实例化两次了。注意构造函数,拷贝构造函数和赋值运算符都声明为私有方法,防止多个实例。
#include<stdio.h> class CSingle1 { public: static CSingle1* getInstance(); void setKey(int k); void printKey(); ~CSingle1(){printf("destructor called\n");} private: CSingle1(){this->key = 0;} CSingle1(const CSingle1&); const CSingle1& operator=(const CSingle1&); static CSingle1 oSingle1;//类中不能有自己类型的对象,除非是static对象 int key; }; CSingle1 CSingle1::oSingle1; CSingle1* CSingle1::getInstance() { return &oSingle1; } void CSingle1::setKey(int k) { key =k; } void CSingle1::printKey() { printf("key:%d\n",key); } int main() { CSingle1 *p1 = CSingle1::getInstance(); p1->setKey(3); CSingle1 *p2 = CSingle1::getInstance(); p2->printKey(); return 0; }
以上是饿汉模式,即无论掉不掉用getInstance,都会存在一个实例。它是线程安全的,但如果实例一直不使用,就浪费了内存。