sofard

导航

智能指针实现

原来的内存管理代码

int main()
{
int *ptr = new(nothrow) int(0);  //关闭异常
if(!ptr) 
{
cout << "new fails."
return 0;
}

if(!check())  ///有校验 ,抛出异常,每次都得管理内存

{

  delete ptr;             //释放
  ptr = nullptr;          //防止空悬指针

 throw exception();

}
delete ptr;             //释放
ptr = nullptr;          //防止空悬指针
return 0;
}

 /////////////////////////////////////////////////////////////////////////////////////////////////

使用引用计数,实现智能指针

1.构造函数中计数初始化为1,拷贝构造函数中计数值加1;

2.析构函数中引用计数减一;

3.赋值运算符中,左边的对象引用计数减一,右边的对象引用计数加一;

4.在赋值运算符和析构函数中,如果减一后为0,则调用delete释放对象。

/////////////////////////////////////////////////////////////////////////////////////////////

智能指针即为封装好的,带计数的指针,需要实现 构造函数,拷贝构造,赋值构造,析构

#include <iostream>
using namespace std;

 

template<class T>  //模板类T,智能指针即为封装好的,带计数的指针
class SmartPtr
{
  public:
  SmartPtr(T *p); //构造函数,参数是普通指针

       SmartPtr(const SmartPtr<T> &orig); // 拷贝构造  ,浅拷贝
  SmartPtr<T>& operator=(const SmartPtr<T> &rhs); // 赋值操作符号,浅拷贝
  ~SmartPtr()    ; //析构函数
  
  private:
  T * ptr;  // 指针
  int *use_count; // 将use_count声明成指针是为了方便对其的递增或递减操作
};

template<class T>
SmartPtr<T>::SmartPtr(T *p) : ptr(p)
{
  try
  {
    use_count = new int(1);   //分配计数内存
  }
  catch (...)
  {
  delete ptr;
  ptr = nullptr;
  use_count = nullptr;
  cout << "Allocate memory for use_count fails." << endl;
  exit(1);  //退出程序
  }

  cout << "Constructor is called!" << endl;
}

template<class T>
SmartPtr<T>::~SmartPtr()
{
  // 只在最后一个对象引用ptr时才释放内存
  if (--(*use_count) == 0)
  {
  delete ptr;
  delete use_count;
  ptr = nullptr;
  use_count = nullptr;
  cout << "Destructor is called!" << endl;
  }
}

template<class T>
SmartPtr<T>::SmartPtr( const SmartPtr<T> &orig)
{
  ptr = orig.ptr;
  use_count = orig.use_count;
  ++(*use_count);
  cout << "Copy constructor is called!" << endl;
}

// 重载等号函数不同于复制构造函数,即等号左边的对象可能已经指向某块内存。
// 这样,我们就得先判断左边对象指向的内存已经被引用的次数。如果次数为1,
// 表明我们可以释放这块内存;反之则不释放,由其他对象来释放。
template<class T>
SmartPtr<T>&   SmartPtr<T>::operator  =  (const SmartPtr<T> &rhs)
{
       //这句话如果放在最后面,那么 rhs=rhs(计数为1的时候),将会释放内存
      ++(*rhs.use_count);

  // 将左操作数对象的使用计数减1,若该对象的使用计数减至0,则删除该对象
       if (--(*use_count) == 0)
  {
    delete ptr;
    delete use_count;
    cout << "Left side object is deleted!" << endl;
  }

  ptr = rhs.ptr;
  use_count = rhs.use_count;

  cout << "Assignment operator overloaded is called!" << endl;
  return *this;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

使用方法

指向单个元素的  智能指针,会有默认内存释放器,也可自己定义

shared_ptr<string> str_point  ( new string("jutta"),
  // 自定义析构函数,lamada表达式
  [](string *p)
  {
  cout << "delete " << *p << endl;
  delete p;
  }
  );

指向数组元素的  智能指针,需要自己定义内存释放函数

shared_ptr<int>  int_point  ( new int[10],
  // 自定义析构函数,lamada表达式
  [](int *p)
  {
  delete[] p;
  }
  );

也可以使用unique_ptr的default_delete函数

shared_ptr<int>  int_point  (new int[10], default_delete <int [] > () );

 

 

share_prt与weak_ptr的区别?

 

 

posted on 2018-10-20 14:18  sofard  阅读(130)  评论(0编辑  收藏  举报