智能指针的原理和简单实现

  1. 什么是智能指针?

    智能指针实质上是一个类,定义一个类来封装资源的分配和释放。这个类的构造函数中传入一个指针,完成资源的分配和初始化。在析构函数中释放传入的该指针,完成资源的释放。

  2. 为什么要用智能指针?

    智能指针就是智能,自动化的管理指针所指向的动态资源。

    例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露。

// case1
void Test2()
{
 int* p1 = new int(2);
 bool isEnd = true;
 //...
 if (isEnd)
 {
  delete p1;
  return;
 }
 //...
 delete p1;
}
// case2
void DoSomeThing()
{
 //...
 throw 2;
 //...
}
void Test2()
{
 int* p1 = new int(2);
 //...
 try {
  DoSomeThing();
 }
 catch (...)
 {
  delete p1;
  throw;
 }
 //...
 delete p1;
}
  • 智能指针的简单实现。

    Auto_ptr:不能共享所有权,只要出现两个指针指向同一块资源,就释放前一个指针的管理权。保证只有一个指针指向一块资源。

    Scoped_ptr:将类中的成员函数拷贝构造和赋值运算符只申明为protected,不定义。所以不可能有两个指针指向同一个对象。

    Shared_ptr:采用引用计数的方法。将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针。

    ScopedArray和Scoped_ptr类似,只是操作的是数组。SharedArray同理。

template <class T>
class AutoPtr
{
public:
 AutoPtr(T*ptr)
  :_ptr(ptr)
 {}
 AutoPtr( AutoPtr<T>&ap)
  :_ptr(ap._ptr)
 {
  ap._ptr = NULL;
 }
 AutoPtr<T>&operator=(const AutoPtr<T>&ap)
 {
  if (this != &ap)
  {
   delete _ptr;
   _ptr = ap._ptr;
   ap._ptr = NULL;
  }
 }
 ~AutoPtr()
 {
  if (_ptr)
  {
   delete _ptr;
   _ptr = NULL;
  }
 }
 
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:
 T*_ptr;
};
struct Node
{
 int _data;
 Node*_next;
};
void Test_AutoPtr()
{
 int*p1 = new int(2);
 int*p2 = p1;
 int*p3 = p2;
 *p3 = 10;
 delete p1;
 AutoPtr<int>ap1(new int(2));
 AutoPtr<int>ap2=ap1;     //此时ap1为NULL,无管理权
 AutoPtr<int>ap3(ap2);
                         //此时ap2为NULL,无管理权
 //*ap2 = 10;            //程序崩溃    
 *ap3 = 10;
 AutoPtr<Node>sp1(new Node);
 sp1->_data = 10;
}
template<class T>
class ScopedPtr
{
public:
 ScopedPtr(T*ptr)
  :_ptr(ptr)
 {}
 
 ~ScopedPtr()
 {
  if (_ptr)
  {
   delete _ptr;
   _ptr = NULL;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:                    //只申明,不定义,防止拷贝构造和赋值运算符重载。
 ScopedPtr(const ScopedPtr<T>&sp);   //保护,防止在外定义。若写为public,则有可能在类外定义。
 ScopedPtr<T>& operator=(const ScopedPtr<T>&sp);
protected:
 T*_ptr;
};
void Test_ScopedPtr()
{
 ScopedPtr<int>sp1(new int(3));
 //ScopedPtr<int>sp2(sp1);             //protectd:无法访问
}
template <class T>
class ScopedArray
{
public:
 ScopedArray(T*ptr)
  :_ptr(ptr)
 {}
 
 ~ScopedArray()
 {
  if (_ptr)
  {
   delete[]_ptr;
  }
 }
 T&operator[](size_t Index)
 {
  return _ptr[Index];
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:
 ScopedArray(const ScopedArray<T>&sp);
 ScopedArray<T>&operator=(const ScopedArray<T>&sp);
protected:
 T*_ptr;
};
void Test_ScopedArray()
{
 ScopedArray<int>sp1(new int[5]);
 //ScopedPtr<int>sp2(sp1);
 
}
template <class T>
class SharedPtr
{
public:
 SharedPtr(T*ptr)
  :_ptr(ptr)
  , _Pcount(new long(1))
 {}
 SharedPtr(const SharedPtr<T>&sp)
  :_ptr(sp._ptr)
  , _Pcount(sp._Pcount)
 {
  ++*(_Pcount);
 }
 //SharedPtr<T>&operator=(const SharedPtr<T>&sp)    //传统写法
 //{
 // if (this != &sp)
 // {
 //  if (--(*_Pcount) == 0)
 //  {
 //   delete _ptr;
 //   delete _Pcount;
 //  }
 //  _ptr = sp._ptr;
 //  _Pcount = sp._Pcount;
 //  ++(*_Pcount);
 // }
 // return *this;
 //}
 SharedPtr<T>&operator=(const SharedPtr<T>sp)     //现代写法
 {
  swap(_ptr, sp._ptr);
  swap(_Pcount, sp._Pcount);
  return *this;
 }
 ~SharedPtr()
 {
  if (--(*_Pcount) == 0)
  {
   delete _ptr;
   delete _Pcount;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
 long GetCount()
 {
  return *_Pcount;
 }
protected:
 T*_ptr;
 long*_Pcount;
};
void Test_SharedPtr()
{
 SharedPtr<int>sp1(new int(2));
 SharedPtr<int>sp2(sp1);
}
template <class T>
class SharedArray
{
public:
 SharedArray(T*ptr)
  :_ptr(ptr)
  , _Pcount(new long (1))
 {}
 SharedArray(const SharedArray<T>&sp)
  :_ptr(sp._ptr)
  , _Pcount(sp._Pcount)
 {
  ++*(_Pcount);
 }
 SharedArray<T>&operator=(const SharedArray<T>sp)     //现代写法
 {
  swap(_ptr, sp._ptr);
  swap(_Pcount, sp._Pcount);
  return *this;
 }
 ~SharedArray()
 {
  if (--(*_Pcount) == 0)
  {
   delete[] _ptr;
   delete _Pcount;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
 T&operator[](size_t Index)
 {
     return _ptr[Index];
 }
 long GetCount()
 {
  return *_Pcount;
 }
protected:
 T*_ptr;
 long*_Pcount;
};
void Test_SharedArray()
{
 SharedArray<int>sp1(new int[5]);
 SharedArray<int>sp2(sp1);
}
时间: 05-23

智能指针的原理和简单实现的相关文章

C++11中智能指针的原理、使用、实现

目录 理解智能指针的原理 智能指针的使用 智能指针的设计和实现 1.智能指针的作用 C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理.程序员自己管理堆内存可以提高了程序的效率,但是整体来说堆内存的管理是麻烦的,C++11中引入了智能指针的概念,方便管理堆内存.使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存. 理解智能指针需要从下面三个层次: 从较浅的层面看,智能指针是利用了一种叫做RAII(资

【转】C++面试题(四)——智能指针的原理和实现

C++面试题(四)——智能指针的原理和实现 tanglu2004 http://blog.csdn.net/worldwindjp/   C++面试题(一).(二)和(三)都搞定的话,恭喜你来到这里,这基本就是c++面试题的最后一波了. 1,你知道智能指针吗?智能指针的原理.     2,常用的智能指针.     3,智能指针的实现. 1答案:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针.智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放, 2,

Chromium和WebKit的智能指针实现原理分析

C++不像Java一样,由虚拟机负责对象分配和释放.也就是说,开发人员使用C++编写代码时,要自己负责对象分配和释放.WebKit和Chromium都是使用C++开发的,因此它们也面临上述问题.在解决对象释放问题时,要做到在对象不需要时自动释放,因为手动释放会带来忘记释放或者释放后又继续使用的隐患.智能指针是实现对象自动释放的有效技术手段.本文就分析Chromium和WebKit的智能指针的实现. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在现实中,

智能指针的原理与设计

     智能指针:实际指行为类似于指针的类对象 ,它的一种通用实现方法是采用引用计数的方法.下面我们来看看智能指针实现的原理和方法: 1.智能指针将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针: 2.每次创建类的新对象时,初始化指针并将引用计数置为1: 3.当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数: 4.对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象

智能指针 与 oc中的指针

智能指针 与 oc中的指针 智能指针的原理及实现 当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝:另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享. 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副

【C/C++学院】0904-boost智能指针/boost多线程锁定/哈希库/正则表达式

boost_array_bind_fun_ref Array.cpp #include<boost/array.hpp> #include <iostream> #include <string> using namespace std; using namespace boost; void mainA () { array <int, 5> barray = { 1, 2, 3, 4, 5 }; barray[0] = 10; barray.at(4)

指针辨析:悬垂指针、哑指针、野指针、智能指针

悬垂指针: 1:提出的原因: 请看下面的代码片段: [cpp] view plaincopyprint? int *p=NULL; void main() { int i=10;p=&i; cout<<"第一次:*p = "<<*p<<endl; cout<<"第二次:*p = "<<*p<<endl; } [cpp] view plaincopyprint? int *p=NULL;

C++智能指针简单剖析

导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. 下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰. 目录

【转】C++智能指针简单剖析

原文链接:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html 导读 最近在补看 <C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的 问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等…….而且在看开源的C++项目 时,也能随处看到智能指针的影子.这说明智能指针不仅