> 文章列表 > 智能指针ok的

智能指针ok的

智能指针ok的

智能指针

模拟实现智能指针
概念
智能指针通常用于对一个资源进行管理,避免因为疏忽或错误造成程序未能释放已经不再使用的内存的情况

智能指针的设计
1、在对象构造时获取资源,在对象析构时释放资源,利用对象的生命周期来控制资源,即RAII特性(利用RALL思想设计delete资源的类)
2、对*和->运算符进行重载,使得智能指针具有指针一样的行为 (像指针一样的行为)
3、智能指针的拷贝问题(根据解决拷贝问题方式的不同,从而衍生出了不同版本的智能指针)

1.auto_ptr
思路是管理权转移,缺点:没有管理权的智能指针不能使用,否则空指针访问崩溃

namespace cl
{template<class T>class auto_ptr{public://RAIIauto_ptr(T* ptr = nullptr):_ptr(ptr){}~auto_ptr(){if (_ptr != nullptr){cout << "delete: " << _ptr << endl;delete _ptr;_ptr = nullptr;}}auto_ptr(auto_ptr<T>& ap):_ptr(ap._ptr){ap._ptr = nullptr; //管理权转移后ap被置空}auto_ptr& operator=(auto_ptr<T>& ap){if (this != &ap){delete _ptr;       //释放自己管理的资源_ptr = ap._ptr;    //接管ap对象的资源ap._ptr = nullptr; //管理权转移后ap被置空}return *this;}//可以像指针一样使用T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr; //管理的资源};
}

2.unique_ptr
思路是防拷贝,缺点:无法对unique_ptr对象进行拷贝
c++11实现:禁止拷贝构造和赋值重载
c++98实现:拷贝构造和赋值重载只声明不实现并且设置private

namespace cl
{template<class T>class unique_ptr{public://RAIIunique_ptr(T* ptr = nullptr):_ptr(ptr){}~unique_ptr(){if (_ptr != nullptr){cout << "delete: " << _ptr << endl;delete _ptr;_ptr = nullptr;}}//可以像指针一样使用T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//防拷贝unique_ptr(unique_ptr<T>& up) = delete;unique_ptr& operator=(unique_ptr<T>& up) = delete;private:T* _ptr; //管理的资源};
}

3.shared_ptr

	template<class T>class shared_ptr{public:shared_ptr(T* ptr = nullptr):_ptr(ptr), _pRefCount(new int(1)), _pmtx(new mutex){}shared_ptr(const shared_ptr<T>& sp):_ptr(sp._ptr), _pRefCount(sp._pRefCount), _pmtx(sp._pmtx){AddRef();}void Release(){_pmtx->lock();bool flag = false;if (--(*_pRefCount) == 0 && _ptr){cout << "delete:" << _ptr << endl;delete _ptr;delete _pRefCount;flag = true;}_pmtx->unlock();if (flag == true){delete _pmtx;}}void AddRef(){_pmtx->lock();++(*_pRefCount);_pmtx->unlock();}shared_ptr<T>& operator=(const shared_ptr<T>& sp){//if (this != &sp)if (_ptr != sp._ptr){Release();_ptr = sp._ptr;_pRefCount = sp._pRefCount;_pmtx = sp._pmtx;AddRef();}return *this;}int use_count(){return *_pRefCount;}~shared_ptr(){Release();}// 像指针一样使用T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get() const{return _ptr;}private:T* _ptr;int* _pRefCount;mutex* _pmtx;};

4.weak_ptr:

	template<class T>class weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptr<T>& sp):_ptr(sp.get()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
}

5. 定制删除器

  • // 定制删除器 考试基本不考,实际使用有价值
  • // 默认情况,智能指针底层都是delete资源
  • // 那么如果你的资源不是new出来的呢?比如:new[]、malloc、fopen // 定制删除器 – 可调用对象

template<class T>
struct DeleteArray
{void operator()(const T* ptr){cout << "delete[]:" << ptr << endl;delete[] ptr;}
};struct DeleteFile
{void operator()(FILE* ptr){cout << "fclose:" << ptr << endl;fclose(ptr);}
};// 释放方式有D删除器决定template<class T, class D = default_delete<T>>class unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}~unique_ptr(){if (_ptr){//cout << "delete:" << _ptr << endl;//delete _ptr;D del;del(_ptr);}}// 像指针一样使用T& operator*(){return *_ptr;}T* operator->(){return _ptr;}unique_ptr(const unique_ptr<T>& sp) = delete;unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;private:T* _ptr;};int main()
{// 删除器在类模板参数给 -- 类型yyk::unique_ptr<A> up1(new A);yyk::unique_ptr<A, DeleteArray<A>> up2(new A[10]);yyk::unique_ptr<FILE, DeleteFile> up3(fopen("test.txt", "w"));// 删除器在构造函数的参数给 -- 对象std::shared_ptr<A> sp1(new A);std::shared_ptr<A> sp2(new A[10], DeleteArray<A>());std::shared_ptr<FILE> sp3(fopen("test.txt", "w"), DeleteFile());std::shared_ptr<A> sp4(new A[10], [](A* p){delete[] p; });std::shared_ptr<FILE> sp5(fopen("test.txt", "w"), [](FILE* p){fclose(p); });return 0;
}