1.c++98的方式是只声明不定义,设置成私有;
2.c++11的方式是=delete,声明为删除函数;
new出来的空间是不会自动调用析构函数的;
方法:
1.将析构函数私有,然后写一个函数公有可以让类外主动去释放堆空间;
2.将构造函数私有就会导致静态成员,栈上的成员和堆上的成员都不能使用,此时可以创建一个静态成员函数,专门用来初始化不同位置的对象,除了构造函数,拷贝构造和赋值重载也需要私有;
方法:
1.将构造函数私有,创建静态函数;要注意的是new除了调用构造函数其实也是可以调用拷贝构造,但是又因为静态成员函数传值返回掉用拷贝构造,所以不能禁止拷贝构造,解决方法是重载operator new删除,使得new被禁止使用
1.c++98将基类构造函数私有或者将析构函数私有,继承规定实例化派生类对象的时候一定要去调用基类的构造函数或者析构函数;
2.c++11使用的是用final修饰及不可以被继承了;
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
饿汉指的是一开始就创建了对象,即在mai函数之前就已经创建好了;坏处就是初始化的内容如果有很多就会导致启动的速度降低,因为启动前要先完成这些准备工作,或者两个单例模式的创建相互依赖,无法保证创建的先后顺序;
1.构造函数私有化;
2.类里面加一个唯一的静态的self类成员,使用getinstance接口获取唯一的静态类对象;
3.拷贝和赋值删除;
4.提供相关功能的接口;
class singleton
{
public:
static singleton &getinstance()
{
return single_;
}
void add(const pair &kv)
{
dict_[kv.first] = kv.second;
}
void print()
{
for (const auto &e : dict_)
{
cout << e.first << ":" << e.second << endl;
}
}
private:
singleton() {}
singleton(const singleton &s) = delete;
singleton &operator=(const singleton &s) = delete;
map dict_;
static singleton single_;
};
singleton singleton::single_;
与饿汉模式唯一的区别就是不能在main函数之前就创建对象;
即在第一次调用getinstance时创建;之后就都是直接返回相关地址;
class singleton_lazy
{
public:
static singleton_lazy *&getinstance()
{
if (single_ == nullptr)
{
single_ = new singleton_lazy;
return single_;
}
return single_;
}
void add(const pair &kv)
{
dict_[kv.first] = kv.second;
}
void print()
{
for (const auto &e : dict_)
{
cout << e.first << ":" << e.second << endl;
}
}
static void destroyinstance()
{
if (single_)
{
delete single_;
single_ = nullptr;
}
}
class GC
{
public:
~GC()
{
destroyinstance();
}
};
private:
singleton_lazy() {}
singleton_lazy(const singleton_lazy &s) = delete;
singleton_lazy &operator=(const singleton_lazy &s) = delete;
~singleton_lazy()
{
cout << "~singleton_lazy" << endl;
FILE *fp = fopen("map.txt", "w");
for (auto &e : dict_)
{
fputs(e.first.c_str(), fp);
fputs(":", fp);
fputs(e.second.c_str(), fp);
fputs("\n", fp);
}
fclose(fp);
}
map dict_;
static singleton_lazy *single_;
static GC gc;
};
singleton_lazy *singleton_lazy::single_ = nullptr;
typename singleton_lazy::GC singleton_lazy::gc;
懒汉模式要注意的是一般单例模式是不需要释放的,程序结束也就释放了;特殊场景如:1.中途需要显示释放,然后在实例化;2.程序结束需要一些特殊处理如持久化;
对于持久化需要显式写一个持久化函数用来调用delete ptr,然后写一个类似智能指针的类gc垃圾回收器,但是只写了析构函数实现自动调用持久化函数,然后实例化一个对象,这样就不怕异常导致的执行流乱跳而内存泄露,可以正常的释放对象。如果有多个类型的单例就将这些单例的持久化函数都写进gc的析构函数里;
也同样可以将gc写到单例的类内部,定义一个静态的gc对象,没有成员变量只占1个字节,这样就可以保证调用的一定是本单例的析构;