lightblueme

许多问题需要说清楚就可以&&走永远比跑来的重要

导航

C++ 智能指针

C++ 智能指针

众所周知,C++和Java的最大的不同在于C++中有一个非常重要的工具——指针。成也萧何败萧何,指针的高效性和灵活性,同时也造成了C++的繁复而不易于管理。指针的管理一旦出现问题,轻则内存泄露,重则系统崩溃。为了应对指针所引起的内存泄露问题,在C++中一些所谓的智能指针异军突起。

一、STL中的实现auto_ptr

auto_ptr本质上是对基指针类型的进一步封装,从而能够对这些指针进行某种程度的更加安全的管理。

auto_ptr的最大的最大的优点是可以有效地应对异常中断问题,假设程序在运行过程当中遇到了异常,那么后面的代码将无法执行,包括了对已经申请的内存进行释放的代码。auto_ptr可以有效地解决这个问题。如下面的代码所示。

class test{
    ...
};

int main(){
  test * t = new test();
  //some operation here
  //but throws the exception
  delete t;  
  return 0;    
}

如代码所示,程序在发生一场之后遇到的内存泄露场景。假设我们使用auto_ptr这种情况就不会发生。

class test{
    ...
};

int main(){
  auto_ptr<test> t (new test());
  //some operation here
  //but throws the exception
  return 0;    
}

就算发生异常,上面申请的内存任然可以被安全释放。因为t对象是放到栈上的,当它从作用域当中退出时,它的析构函数会被自动调用,从而释放它所管理的内存对象(及时发生异常,这个过程也会发生)

注意上面的auto_ptr的定义方式必须使用初始化的直接方式(也就是将参数传到紧跟在对象名后面的括号当中),因为他的构造函数是explicit的。

上面的规定是非常合理的,但是除却上面的规定,剩余的语法,让人感觉匪夷所思。

第一、复制和赋值都是破坏性的。当我们讲一个对象通过调用复制构造函数赋值给另一个auto_ptr时,会造成原来的auto_ptr的销毁,也就是它的基对象指针变成了未被绑定的状态。

auto_ptr<test> t(new test());
auto_ptr<test> t1(t);
这是我们可以测试t的绑定状态
if(t.get())
  cout<<"not null"<<endl;
else
  cout<<"null"<<endl;

上面的get的用法为,如果t为未绑定状态返回0,否则返回1。显然上面的代码返回的为0,输出 null。因为在复制操作中,它已经被重置为为绑定状态了。

对于赋值操作,具有同样的效果。

第二、release和reset

给人的直接感觉是release是释放内存的,但是事实上,它只是设置当前智能指针为未绑定状态,若要释放内存必须使用后面的reset方法。

即使release之后,我们仍然可以调用该对象的reset来释放内存。

auto_ptr<test> t(new test());
t.release();//the memory is not released
t.reset();//the memory is released acutually

上面的reset还有其它的功能,比如我们可以将其指向一个新的内存指针,这同样是破坏性的。

假设刚开始auto_ptr没有绑定任何内存,则OK

如果绑定了任何一个指针,那么它会首先释放之。

正式基于auto_ptr的种种不便,boost库中的share_ptr兴起。

二、Boost shared_ptr

详细可以参考[1]

 

[1] http://www.cnblogs.com/TianFang/archive/2008/09/19/1294521.html

posted on 2015-06-09 15:14  lightblueme  阅读(241)  评论(0编辑  收藏  举报