共享指针
主要是在设计模式中,老师多次提及共享指针,尤其是在单例的情况下,可以避免内存泄漏。
定义
共享指针shared_ptr 是存储动态创建对象的指针(new),其主要功能是管理动态创建对象的销毁,从而帮助彻底消除内存泄漏和悬空指针(野指针)的问题。
实质就是对创建出的一个相应类型下的对象的指针,但其类型为shared_ptr类型而非对象所对应的原类型。
原理
基本原理:记录对象被引用的次数来实现的,当引用次数为 0 的时候,也就是最后一个指向该对象的共享指针析构的时候,共享指针的析构函数就把指向的内存区域释放掉。
每一个共享指针在内部实际指向两个内存位置:
- 引用计数的指针
- 对象的指针
当新的 shared_ptr 对象与对象指针关联时:则在其构造函数中,将与此指针关联的引用计数增加1。
当任何 shared_ptr 对象被析构超出作用域时,则在其析构函数中,它将关联的对象指针的引用计数减1。如果引用计数变为0,则表示没有其他 shared_ptr 对象与此内存关联,在这种情况下,它使用delete函数删除该内存。
使用
- 构造
std::shared_ptr<Typename> ptr(new Typename);
或
std::shared_ptr<Typename> ptr;
ptr=std::shared_ptr<Typename>(new Typename);
- 拷贝构造
std::shared_ptr<Typename> ptr1(new Typename);
std::shared_ptr<Typename> ptr2(ptr1);//使用拷贝构造函数的方法,会让引用计数加 1
- 赋值
std::shared_ptr<Typename> ptr1(new Typename);
std::shared_ptr<Typename> ptr2;//此时ptr2为NULL
ptr2=ptr1;//ptr2由NULL变为指向与ptr1相同指向对象的指针,并且对应的对象引用次数+1
- use_count()
得到对象被引用次数
ptr1.use_count();
- reset()
ptr1.reset();//重置指针,并将对应对象引用次数减1
- get()
获取对象原类型的指针,不建议。
Typename* oriPtr=ptr1.get();
单例模式的类模板
将该模板放置Singleton.h头文件中
#include <memory>
template<typename T>
class Singleton{
public:
static T& getInstance();//静态行为,可通过类直接调用获取单例对象
protected:
Singleton(){}
void initialize(){}
private:
Singleton(const Singleton & ) =delete;//禁止拷贝构造
Singleton(Singleton &&)=delete;
Singleton & operator=(const Singleton &)=delete;//禁止赋值
}
template<typename T>
T& Singleton<T>::getInstance(){
//使用共享指针实现
static std::shared_ptr<T> instance;
if(!instance){
instance=std::shared_ptr<T>(new T);
instance->initialize();
}
return *instance;//返回单例对象的引用。
}
MenuMgr要实现单例模式,继承Singleton类即可,如下:
#include "Singleton.h"
class MenuMgr:public Singleton<MenuMgr>{
public:
void setMenu(int MenuID){}
}
要获得MenuMgr的单例,通过类MenuMgr使用其静态函数getInstance()即可。
MenuMgr* menu_mgr=MenuMgr::getInstance();