RAII
问题:
申请资源
使用
释放资源 ---- 通常遗忘 --- 内存泄漏 fd
使用对象的自动析构的方式,进行所申请资源的自动释放
auto_ptr
禁止隐式构造
允许拷贝构造
允许等号运算符
不能让多个智能指针指向同一块空间
不能用auto_ptr直接传参,否则会直接崩溃
传引用可以
显式构造带有类型
隐式的不带类型
int* p1 = new int(100); //auto_ptr<int> p2 = auto_ptr<int>(p1); 显式 //auto_ptr<int> p2 = p1;隐式 auto_ptr<int>p2(p1);//显式 auto_ptr<int> p3(new int(10)); //p2 = p3; //此时把p3指针放入p2,p3指针不存在,所以解引用p3会崩溃
//p2开始存p1指针,接收p3后,p1被释放掉,所以p1无效
// //cout << *p1 << endl;//无效 、//解引用p1 //cout << *p2 << endl;//10 //cout << *p3 << endl;//崩溃 //auto_ptr<int> p4 = p2; //cout << *p1 << endl; //cout << *p2 << endl; //cout << *p3 << endl;
//获取指针 int* tmp1 = p2.get(); cout << *tmp1 << endl; //转移 int* tmp2 = p2.release(); //cout << *p2 << endl;//崩溃 p2.reset(p1); //重置自身 干掉自身本来的指针,获取新的指针 vector<auto_ptr<int>> v; //auto_ptr 不能使用容器 //加入容器的过程是等号运算符重载 //p2会无效 v.push_back(p2);
#ifndef MAUTO_PTR_H #define MAUTO_PTR_H template<typename T> class Mauto_ptr { private: T* _ptr; public: //explicit防止隐式构造 explicit Mauto_ptr(T* ptr = NULL)//构造函数 { _ptr = ptr; } Mauto_ptr(Mauto_ptr& src)//拷贝构造 { _ptr = src._ptr; src._ptr = NULL; } Mauto_ptr<T>& operator=(Mauto_ptr& src)//等号运算符重载 { if (this == &src) { return *this; } if (NULL != _ptr) { delete _ptr; } _ptr = src._ptr; src._ptr = NULL; } T& operator*()//解引用运算符 { return *_ptr; } T* operator->() { return _ptr; } T* get() { return _ptr; } T* release() { T* tmp = _ptr; _ptr = NULL; return tmp; } void reset(T* ptr = NULL)//把自己重新换个值 { if (NULL != _ptr) { delete _ptr; } _ptr = ptr; } ~Mauto_ptr() { if (NULL != _ptr) { delete _ptr; } _ptr = NULL; } };
unique_ptr(唯一的指针)
允许隐式构造
不允许拷贝构造
不允许等号运算符
不能让多个智能指针指向同一块空间
和auto_ptr 比较
允许隐式构造
不允许拷贝构造
不允许等号运算符
可以加入数组指针
存在move函数进行指针转移
进行指针delete的时候调用删除器
int* p1 = new int(10); unique_ptr<int> p2(p1); cout << *p2 << endl; //p2.reset(p1); cout << *p2 << endl; //unique_ptr<int> p3(p1); //unique_ptr<int> p3 = p2;//不允许拷贝构造 unique_ptr<int> p4; //p4 = p2;//不允许等号运算符重载 //int* arr = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9}; //unique_ptr<int[]> parr(arr); //cout << parr[2] << endl; //operator bool /* if (parr) { }*/ //parr.swap() //和release完成的功能一致 p4 = move(p2);//把p2干掉转移到p4 //p4 = new int(10); cout << *p4 << endl; unique_ptr<int> p6 = fun(p4); cout << *p6 << endl; vector<unique_ptr<int>> v;//直接引用 //v.push_back() vector<auto_ptr<int>> v1; auto_ptr<int> p7(new int(100)); v1.push_back(auto_ptr<int>(new int(100))); cout << *(v1[0]) << endl; //cout << *p7 << endl;
#ifndef MUNIQUE_PTR #define MUNIQUE_PTR template<typename T> class Munique_ptr { private: T* _ptr; public: //explicit防止隐式构造 Munique_ptr(T* ptr = NULL) { _ptr = ptr; } //delete的成员方法不允许再生成 Munique_ptr(Munique_ptr& src) = delete; Munique_ptr<T>& operator=(Munique_ptr& src) = delete; //&& 右值引用 --- 引用一个马上释放的对象 Munique_ptr(Munique_ptr&& src) { _ptr = src._ptr; } Munique_ptr<T>& operator=(Munique_ptr&& src) { _ptr = src._ptr; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } T& operator[](int pos) { return _ptr[pos]; } //bool运算符的重载 bool operator bool() { return _ptr; } void swap(Munique_ptr<T>& src) { T* tmp = _ptr; _ptr = src._ptr; src._ptr = tmp; } T* get() { return _ptr; } T* release() { T* tmp = _ptr; _ptr = NULL; return tmp; } void reset(T* ptr = NULL) { if (NULL != _ptr) { delete _ptr; } _ptr = ptr; } ~Munique_ptr() { if (NULL != _ptr) { delete _ptr; } _ptr = NULL; } }; template<typename T> Munique_ptr<T>&& mmove(Munique_ptr<T>& src)//允许传引用,不允许传参 { return src.release() }
shared_ptr(强智能指针)
有引用计数
交叉引用会引起无法释放
有引用计数
#include"mshared_ptr.h" #include"mweak_ptr.h" template<typename T> map<T*, int>* Mshared_ptr<T>::_map = new map<T*, int>; template<typename T> mutex Mshared_ptr<T>::_mu; class Pb; class Pa { public: Pa(Pb* pb = NULL) {} Mweak_ptr<Pb> _pb; }; class Pb { public: Pb(Pa* pa = NULL) {} Mweak_ptr<Pa> _pa; }; int main() { /* shared_ptr 有引用计数 交叉引用会引起无法释放 */ #if 0 int* p1 = new int(100); Mshared_ptr<int> p2(p1); Mshared_ptr<int> p3 = p2; Mshared_ptr<int> p4; p4 = p3; cout << p2.use_count() << endl;//use_count:返回计数器 Mshared_ptr<int>* p5 = new Mshared_ptr<int>(p1); cout << p2.use_count() << endl; delete p5; cout << p2.use_count() << endl; #endif Mshared_ptr<Pa> spa = new Pa(); Mshared_ptr<Pb> spb = new Pb(); cout << spa.use_count() << endl; cout << spb.use_count() << endl;
#ifndef MSHAERD_PTR_H #define MSHAERD_PTR_H #include<iostream> #include<map> #include<iterator> #include<mutex> using namespace std; template<typename T> class Mshared_ptr { private: T* _ptr; static map<T*, int>* _map; static mutex _mu; public: Mshared_ptr(T* ptr = NULL) { cout << "Mshared_ptr(T* ptr = NULL)" << endl; _ptr = ptr; typename map<T*, int>::iterator it = _map->find(ptr); if (it != _map->end()) { _mu.lock(); it->second++;//计数器++操作 _mu.unlock(); } else { _mu.lock(); _map->insert(make_pair(_ptr, 1)); _mu.unlock(); } } Mshared_ptr(const Mshared_ptr<T>& src) { cout << "Mshared_ptr(Mshared_ptr<T>& src)" << endl; _ptr = src._ptr; _mu.lock(); (*_map)[_ptr]++; _mu.unlock(); } Mshared_ptr<T> operator=(const Mshared_ptr<T>& src) { cout << "Mshared_ptr<T> operator=(Mshared_ptr<T>& src);" << endl; if (_ptr == src._ptr) { return *this; } _mu.lock(); if (0 == --(*_map)[_ptr])//引用计数为空 { if (NULL != _ptr) { delete _ptr; } } _ptr = src._ptr; (*_map)[_ptr]++; _mu.unlock(); return*this; } ~Mshared_ptr() { cout << "~Mshared_ptr()" << endl; _mu.lock(); if (0 == --(*_map)[_ptr]) { if (NULL != _ptr) { cout << "delete" << endl; delete _ptr; } } _mu.unlock(); _ptr = NULL; } T& operator*()//解引用 { return *_ptr; } T* operator->() { return _ptr; } T& operator[](int pos) { return _ptr[pos]; } /* T* operator bool() { return _ptr; }*/ T* get() { return _ptr; } int use_count() { return (*_map)[_ptr]; } };
交叉引用会引起无法释放
Mshared_ptr<Pa> spa = new Pa(); Mshared_ptr<Pb> spb = new Pb(); cout << spa.use_count() << endl; cout << spb.use_count() << endl;
weak_ptr(弱智能指针)
不能直接使用
防止交叉引用
如果weak_ptr转换为shared_ptr,如果指向的内存已
释放,就会转换失败
多线程时候用来进行不确定生存周期的指针的
多线程传递
#include"mshared_ptr.h" #include"mweak_ptr.h" template<typename T> map<T*, int>* Mshared_ptr<T>::_map = new map<T*, int>; template<typename T> mutex Mshared_ptr<T>::_mu; class Pb; class Pa { public: Pa(Pb* pb = NULL) {} Mweak_ptr<Pb> _pb; }; class Pb { public: Pb(Pa* pa = NULL) {} Mweak_ptr<Pa> _pa; }; Mshared_ptr<Pa> spa = new Pa(); Mshared_ptr<Pb> spb = new Pb(); cout << spa.use_count() << endl; cout << spb.use_count() << endl; spa->_pb = spb.get(); spb->_pa = spa.get(); cout << spa.use_count() << endl; cout << spb.use_count() << endl; //Mweak_ptr<int> wp1 = new int(10);//weak:不能直接引用 错误
//不占引用计数,析构的时候也不用delete //cout << *wp1 << endl; //Mshared_ptr<int> sp1 = wp1.lock();//转换shared_ptr,才可以使用
//若要用,让wp1lock一下,返回一个强制指针 //cout << *sp1 << endl;
#ifndef MWEAK_PTR_H #define MWEAK_PTR_H #include"mshared_ptr.h" template<typename T> class Mweak_ptr { private: T* _ptr; public: Mweak_ptr(T* ptr = NULL) { _ptr = ptr; } Mweak_ptr(Mweak_ptr<T>& src) { _ptr = src._ptr; } Mweak_ptr<T>& operator=(Mweak_ptr<T>& src) { _ptr = src._ptr; return *this; } T* operator=(T* ptr) { _ptr = ptr; return ptr; } ~Mweak_ptr() {} Mshared_ptr<T> lock() { return Mshared_ptr<T>(_ptr); } };