昨天写了个单例模式,当时感觉有个问题:
new出来的对象一直没有释放!这不是内存泄露吗?
后来就看了别人的代码,java中是没有的,因为不需要。又看了一份c++的,也没有。我就想,可能不需要吧,在程序运行期间,最多只有一个instance,不会耗尽内存的,最多O(1)的内存。
可是今天怎么考虑觉得这种解释太牵强了!如果对象很大呢?如果有很多类的单例instance呢?
于是又继续查,发现很多人都没有写析构函数,但是有些还是有的。
所以,析构函数还是需要的。一个完美的代码是不能有潜在bug的。
既然需要一个析构函数,那么在哪里调用呢?在程序结束后手动调用?显然这样不好。因为我们不知道什么时候不再需要这个对象。
再网上看到别人一个巧妙的解决方法:
使用一个内部类负责析构。感觉有点像代理模式了?
因为任何静态对象在程序运行期间都存在,生命期结束后都会被收回。所以可以让这个静态对象析构的时候析构这个单例对象。
其实还有另外一个问题,很大的bug:
虽然定义了protected的构造函数,但是仍然不能保证只有一个instance,因为还有拷贝构造函数和赋值构造函数,调用的话编译器会合成。。。
改进后的代码:
#include <iostream>
using namespace std;
class Singleton
{
protected:
Singleton() {cout<<"con of Singleton"<<endl;}
~Singleton(){cout<<"dcon of Singleton"<<endl;}
Singleton(const Singleton& s);///只定义,不实现
public:
static Singleton * getInstance()
{
if(_instance==0)
{
_instance = new Singleton();
}
return _instance;
}
///other class functions...
void show()
{
cout<<"This is a Singleton !"<<endl;
}
private:
static Singleton * _instance;
///other class members ...
class Proxy
{
public:
~Proxy()
{
if(_instance!=0)
{
delete _instance;
_instance = 0;
}
}
};
static Proxy pt;
};
///静态成员的初始化
Singleton* Singleton::_instance = 0;//new Singleton();
Singleton::Proxy Singleton::pt;
int main()
{
Singleton *s=Singleton::getInstance();
s->show();
Singleton *a=Singleton::getInstance();
a->show();
cout<<(a == s)<<endl;
//Singleton b; ///compile error!
//Singleton c(*s);///compile error!
//Singleton d=*a;///compile error!
return 0;
}
考虑优化,如果在程序中大量调用getInstance(),除了第一次判断成功外,其他情况下这段代码
if(_instance==0)
{
_instance = new Singleton();
}
显得很多余!
可以在初始化时就创建一个对象:
Singleton* Singleton::_instance = new Singleton();
然后把上面的if 代码段删除,就可以了。
如果不是返回指针,使用引用即可:
#include <iostream>
using namespace std;
class Singleton
{
protected:
Singleton() {cout<<"con of Singleton"<<endl;}
~Singleton(){cout<<"dcon of Singleton"<<endl;}
Singleton(const Singleton& s);///只定义,不实现
public:
static Singleton & getInstance()
{
return _instance;
}
///other class functions...
void show()
{
cout<<"This is a Singleton !"<<endl;
}
private:
static Singleton & _instance;
///other class members ...
class Proxy
{
public:
~Proxy()
{
_instance.~Singleton();
}
};
static Proxy pt;
};
///静态成员的初始化
Singleton& Singleton::_instance = *(new Singleton());
Singleton::Proxy Singleton::pt;
int main()
{
Singleton &s=Singleton::getInstance();
s.show();
Singleton &a=Singleton::getInstance();
a.show();
cout<<(&s==&a)<<endl;
return 0;
}