为什么需要智能指针?
用来解决申请出来的空间,没有进行及时释放,造成内存泄漏的问题。
内存泄漏不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
而智能指针则是解决内存泄漏的事前预防型方案!
在对象构造时获取资源,在对象析构时释放资源。
RAII思想:根据对象的生命周期控制资源的生命周期
RAII一个应用: 智能指针 -->根据智能指针对象的生命周期控制动态开辟的资源的生命周期
template <class T>
class smartPtr
{
public:
smartPtr(T* ptr)
:_ptr(ptr)
{}
~smartPtr()
{
if (_ptr)
{
delete _ptr;
cout << "~smartPtr delete" << endl;
}
}
//管理权转移
smartPtr(smartPtr<T>& sp)
:_ptr(sp._ptr)
{
sp._ptr = nullptr;
}
smartPtr<T>& operator=(smartPtr<T>& sp)
{
if (this != &sp)
{
//释放原有资源
if (_ptr)
delete _ptr;
//管理权转移
_ptr = sp._ptr;
sp._ptr = nullptr;
}
return *this;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
private:
T* _ptr;
};
C++库中智能指针都定义在memory
这个头文件之中。
实现的原理:管理权转移的思想。
void testAutoPtr()
{
//auto_ptr: 一般禁止使用, 有解引用异常的风险
auto_ptr<Date> ap(new Date);
cout << ap->_year << endl;
//拷贝时发生管理权转移
auto_ptr<Date> copy = ap; //当对象拷贝或者赋值后,前面的对象就悬空了
//发生管理权转移之后,智能指针不再拥有资源,故不能访问资源
//cout << ap->_year << endl;
cout << copy->_year << endl;
}
设计思路:防拷贝,直接不让拷贝和赋值
template <class T>
class uniquePtr
{
uniquePtr(T* ptr)
:_ptr(ptr)
{}
~uniquePtr()
{
if (_ptr)
delete _ptr;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
//防拷贝
uniquePtr(const uniquePtr<T>& up) = delete;
uniquePtr<T>& operator=(const uniquePtr<T>& up) = delete;
private:
T* _ptr;
};
void testUniquePtr()
{
unique_ptr<Date> up(new Date);
//unique_ptr: 防拷贝-->拷贝构造和赋值运算符定义为delete函数
/*unique_ptr copy = up;
unique_ptr up2(new Date);
up2 = up;*/
}
原理:时通过引用计数的方式来实现多个shared_ptr对象之间共享资源
void testSharedPtr()
{
shared_ptr<Date> sp(new Date);
cout << sp->_year << endl;
cout << sp.use_count() << endl;
shared_ptr<Date> copy(sp);
cout << sp->_year << endl;
cout << sp.use_count() << endl;
shared_ptr<Date> sp2(new Date);
sp2 = sp;
cout << sp->_year << endl;
cout << sp.use_count() << endl;
}
template <class T, class deletor>
class sharedPtr
{
public:
sharedPtr(T* ptr, deletor del)
:_ptr(ptr)
, _useCount(new int(1))
, _mtx(new mutex)
, _del(del)
{}
~sharedPtr()
{
//引用计数自减
//if (--(*_useCount) == 0)
if (subRef() == 0)
{
//delete _ptr;
//定制删除器进行空间释放
del(_ptr);
delete _useCount;
delete _mtx;
cout << "~sharedPtr" << endl;
}
}
sharedPtr(const sharedPtr<T>& sp)
:_ptr(sp._ptr)
, _useCount(sp._useCount)
, _mtx(sp._mtx)
{
//++(*_useCount);
addRef();
}
sharedPtr<T>& operator=(const sharedPtr<T>& sp)
{
//if (this != &sp)
//判断管理的资源是否相同
if (_ptr != sp._ptr)
{
//判断当前管理的资源是否需要释放
//if (--(*_useCount) == 0)
if (subRef() == 0)
{
delete _ptr;
delete _useCount;
delete _mtx;
}
//赋值
_ptr = sp._ptr;
_useCount = sp._useCount;
_mtx = sp._mtx;
//++(*_useCount);
addRef();
}
return *this;
}
int getUseCount()
{
return *_useCount;
}
int addRef()
{
_mtx->lock();
++(*_useCount);
_mtx->unlock();
return *_useCount;
}
int subRef()
{
_mtx->lock();
--(*_useCount);
_mtx->unlock();
return *_useCount;
}
private:
T* _ptr;
int* _useCount;
mutex* _mtx;
deletor _del;
};
template <class T>
struct ListNode
{
/*shared_ptr> _prev;
shared_ptr> _next;*/
weak_ptr<ListNode<T>> _prev;
weak_ptr<ListNode<T>> _next;
~ListNode()
{
cout << "~ListNode" << endl;
}
};
void testSharedPtr5()
{
shared_ptr<ListNode<int>> sp(new ListNode<int>);
shared_ptr<ListNode<int>> sp2(new ListNode<int>);
cout << sp.use_count() << endl;
cout << sp2.use_count() << endl;
sp->_next = sp2;
sp2->_prev = sp;
cout << sp.use_count() << endl;
cout << sp2.use_count() << endl;
//weak_ptr: 不能直接使用,需要用shared_ptr进行初始化, 专门解决特殊场景下shared_ptr循环引用的问题
//weak_ptr> wp(new ListNode);
}
//定制删除器
template <class T>
struct deleteArray
{
void operator()(T* ptr)
{
delete[] ptr;
cout << "delete Array" << endl;
}
};
template <class T>
struct freeM
{
void operator()(T* ptr)
{
free(ptr);
cout << "free" << endl;
}
};
void testSharedPtr6()
{
/*deleteArray da;
shared_ptr sp(new A[100], da);*/
freeM<int> fm;
shared_ptr<int> sp((int*)malloc(sizeof(int)), fm);
}