智能指针

1.智能指针是RAII思想的一种产品, RAII:Resource Acquistion Is Initialization ,资源分配就初始化,定义一个类来封装资源的分配和释放。在构造函数里完成资源分配初始化,在析构函数里完成资源的清理。 通常是经由类模板来实现。借由模板来达成泛型,通常借由类的析构函数来达成自动释放指针所指向的内存或对象。

第一个阶段(C++98):

auto_ptr:自动指针,它的主要思想是管理权转移,但其存在很大的缺陷,当要进行拷贝构造或者赋值相关操作时,原来的智能指针就失去意义,此时只有新的智能指针可以使用。简单点说,就是任何时候只能有一个智能指针指向那块空间,这样在使用上造成了很大的不便。

第二个阶段(C++03):

即第三方库Boost库中的智能指针:

scoped_ptr:守卫指针,它的主要思想就是防拷贝

shared_ptr:共享指针,顾名思义就是共享同一块空间,它的主要思想是引入引用计数,但存在循环引用的缺陷。

weak_ptr:弱指针,它主要用来配合共享指针解决共享指针的循环引用的缺陷。

第三阶段(C++11):

unique_ptr:如同boost库中的scoped_ptr,主要思想就是防拷贝

shared_ptr:它的主要思想是引入引用计数,但存在循环引用的缺陷。

weak_ptr:弱指针,它主要用来配合共享指针解决共享指针的循环引用的缺陷。

2.auto_ptr:自动指针,它的主要思想是管理权转移,但其存在很大的缺陷,当要进行拷贝构造或者赋值相关操作时,原来的智能指针就失去意义,此时只有新的智能指针可以使用。简单点说,就是任何时候只能有一个智能指针指向那块空间,这样在使用上造成了很大的不便。

scoped_ptr:守卫指针,它的主要思想就是防拷贝

shared_ptr: 共享指针,顾名思义就是共享同一块空间,它的主要思想是引入引用计数,但存在循环引用的缺陷。

weak_ptr: 弱指针,它主要用来配合共享指针解决共享指针的循环引用的缺陷。

3.

#include<iostream>
#include<string>
using namespace std;
template <class T>
class AutoPtr    //  模拟实现auto_ptr
{
public:
 AutoPtr(T* ptr = NULL)
  :_ptr(ptr)
 {}
 AutoPtr(AutoPtr<T>& ap)
 {
  _ptr = ap._ptr;
  ap._ptr = NULL;
 }
 AutoPtr<T>& operator = (AutoPtr<T>& ap)
 {
  if (_ptr != ap._ptr)
  {
   if (_ptr)
   {
    delete _ptr;
   }
   _ptr = ap._ptr;
   ap._ptr = NULL;
  }
  return *this;
 }
 T& operator *()
 {
  return *_ptr;
 }
 T* operator ->()
 {
  return _ptr;
 }
 ~AutoPtr()
 {
  cout << "~AutoPtr()" << endl;
  if (_ptr)
  {
   delete _ptr;
  }
 }
private:
 T* _ptr;
};
void TestAutoPtr()
{
 AutoPtr<int>ptr1(new int(10));
 AutoPtr<int>ptr2(ptr1);
 AutoPtr<int>ptr3(ptr2);
 cout << *ptr3 << endl;
}

template <class T>
class ScopedPtr     //scoped_ptr的模拟实现
{
public:
 ScopedPtr(T* ptr = NULL)
  :_ptr(ptr)
 {}
 T* operator ->()
 {
  return _ptr;
 }
 T& operator *()
 {
  return *_ptr;
 }
private:
 T* _ptr;
 ScopedPtr<T>(ScopedPtr<T>& ap);
 ScopedPtr<T>& operator = (ScopedPtr<T>& ap);
};
void TestScopedPtr()
{
 ScopedPtr<int>ptr1(new int(6));
}
template <class T>
class SharedPtr
{
public:
 SharedPtr(T* ptr = NULL)
  :_ptr(ptr)
  : _refcount(new int(1))
 {}
 SharedPtr(const SharedPtr<T>& sp)
 {
  if (_ptr != sp._ptr)
  {
   if (--(*_refcount) == 0)
   {
    delete _ptr;
    delete _refcount;
   }
   _ptr = sp._ptr;
   _refcount = sp._refcount;
   (*_refcount)++;
  }
   return *this;
 }
 T* GetPtr()
 {
  return _ptr;
 }
 T* operator->()
 {
  return _ptr;
 }
 T& operator*()
 {
  return *_ptr;
 }
 ~SharedPtr()
 {
  if (--(*_refcount) == 0)
  {
   delete _ptr;
   delete _refcount;
  }
 }
private:
 T* _ptr;
 T* _refcount;
};
void TestSharedPtr()
{
 SharedPtr<int>ptr1(new int(1));
 SharedPtr<int>ptr2(ptr1);
 SharedPtr<int>ptr3(new int(3));
 ptr1 = ptr3;
}
template <class T>
class WeakPtr
{
public:
 WeakPtr()
  :_ptr(NULL)
 {}
 WeakPtr(SharedPtr < T& s)
  :_ptr(s.GetPtr())
 {}
 T* GetPtr()
 {
  return _ptr;
 }
 T* operator->()
 {
  return _ptr;
 }
 T& operator*()
 {
  return *_ptr;
 }
 private:
  T* _ptr;
};
struct ListNode
{
 WeakPtr<ListNode> _prev;
 WeakPtr<ListNode> _next;
 ~ListNode()
 {
  cout << "~ListNode()" << endl;
 }
};
void TestWeakPtr()
{
 SharedPtr<ListNode> cur = new ListNode;
 SharedPtr<ListNode> next = new ListNode;
 cur->_next = next;
 next->_prev = cur;
}
4.循环引用就是两个对象互相使用一个Shared_ptr成员变量指向对方会造成循环引用,导致引用计数失效。
解决办法:

1. 当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
2. 当A的生存期超过B的生存期的时候,B改为使用一个普通指针指向A。
3. 使用弱引用的智能指针打破这种循环引用。












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值