您的位置:首页 > 其它

智能指针Boost.smart_ptr学习1--为什么使用智能指针

2011-10-04 13:59 309 查看
我们学习C++都知道智能指针,例如STL中的std::auto_ptr,但是为什么要使用智能指针,使用它能带给我们什么好处呢?

最简单的使用智能指针可以不会因为忘记delete指针而造成内存泄露。还有如果我们开发或者使用第三方的lib中的某些函数需要返回指针,这样的返回的指针被client使用的时候,lib就会失去对返回的指针的控制,这样delete的指针的任务一般就会交给调用方client,但是如果 client忘记调用delete或是调用的时机不正确,都有可能导致问题,在这种情况下就最好使用智能指针。还有使用智能指针可以保证异常安全,保证程序在有异常抛出时仍然无内存泄露。

std::auto_ptr很多的时候并不能满足我们的要求,比如她不能用在STL的container中。boost的smart_ptr中提供了4种智能指针和2种智能指针数组来作为std::auto_ptr的补充。

shared_ptr<boost/shared_ptr.hpp>:使用shared_ptr进行对象的生存期自动管理,使得分享资源所有权变得有效且安全.

scoped_ptr<boost/scoped_ptr.hpp>: 用于确保能够正确地删除动态分配的对象。scoped_ptr 有着与std::auto_ptr类似的特性,而最大的区别在于它不能转让所有权而auto_ptr可以。事实上,scoped_ptr永远不能被复制或被赋值!scoped_ptr 拥有它所指向的资源的所有权,并永远不会放弃这个所有权。

weak_ptr<boost/weak_ptr.hpp>:weak_ptr 是 shared_ptr 的观察员。它不会干扰shared_ptr所共享的所有权。当一个被weak_ptr所观察的 shared_ptr 要释放它的资源时,它会把相关的 weak_ptr的指针设为空。使用此辅助指针一般是防止悬空指针。

intrusive_ptr<boost/intrusive_ptr.hpp>:shared_ptr的插入是版本,一般不使用,因为需要对使用此指针的类型中增加ref计数功能。但是可以保证不增加指针的大小。

scoped_array<boost/scoped_array.hpp>: scoped_array 为数组做了scoped_ptr为单个对象的指针所做的事情:它负责释放内存。shared_array<boost/shared_array.hpp>: shared_array 用于共享数组所有权的智能指针。一般指向std::vector的shared_ptr提供了比shared_array更多的灵活性,所以一般使用 std::vector<shared_ptr>。

Smart_ptr库如何改进你的程序?

使用shared_ptr进行对象的生存期自动管理,使得分享资源所有权变得有效且安全。

使用weak_ptr可以安全地观测共享资源,避免了悬挂的指针。

使用scoped_ptr 和 scoped_array限制资源的使用范围,使得代码更易于编写和维护,并有助于写出异常安全的代码。

智能指针解决了资源生存期管理的问题(尤其是动态分配的对象). 智能指针有各种不同的风格。多数都有一种共同的关键特性:自动资源管理。这种特性可能以不同的方式出现:如动态分配对象的生存期控制,和获取及释放资源 (文件, 网络连接)。Boost的智能指针主要针对第一种情况,它们保存指向动态分配对象的指针,并在正确的时候删除这些对象。你可能觉得奇怪为什么这些智能指针不多做一点工作。它们不可以很容易就覆盖所有资源管理的不同情况吗?是的,它们可以(在一定范围内它们可以),但不是没有代价的。通用的解决方案意味着更高的复杂性,而对于Boost的智能指针,可用性比灵活性具有更高的优先级。但是,通过对可定制删除器的支持,Boost的最智能的智能指针(boost::shared_ptr)可以支持那些不是使用delete进行析构的资源。Boost.Smart_ptr的五个智能指针类型是专门特制的,适用于每天的编程中最常见的需求。

何时我们需要智能指针?

有三种典型的情况适合使用智能指针:

资源所有权的共享

要编写异常安全的代码时

避免常见的错误,如资源泄漏

共享所有权是指两个或多个对象需要同时使用第三个对象的情况。这第三个对象应该如何(或者说何时)被释放?为了确保释放的时机是正确的,每个使用这个共享资源的对象必须互相知道对方,才能准确掌握资源的释放时间。从设计或维护的观点来看,这种耦合是不可行的。更好的方法是让这些资源所有者将资源的生存期管理责任委派给一个智能指针。当没有共享者存在时,智能指针就可以安全地释放这个资源了。

异常安全,简单地说就是在异常抛出时没有资源泄漏并保证程序状态的一致性。如果一个对象是动态分配的,当异常抛出时它不会自动被删除。由于栈展开以及指针离开作用域,资源可以会泄漏直至程序结束(即使是程序结束时的资源回收也不是由语言所保证的)。不仅可能程序会由于内存泄漏而耗尽资源,程序的状态也可能变得混乱。智能指针可以自动地为你释放这些资源,即使是在异常发生的情况下。

避免常见的错误。忘记调用 delete 是书本中最古老的错误(至少在这本书中)。一个智能指针不关心程序中的控制路径;它只关心在它所指向的对象的生存期结束时删除它。使用智能指针,你不再需要知道何时删除对象。并且,智能指针隐藏了释放资源的细节,因此使用者不需要知道是否要调用 delete, 有些特殊的清除函数并不总是删除资源的。

安全和高效的智能指针是程序员的军火库中重要的武器。虽然C++标准库中提供了 std::auto_ptr, 但是它不能完全满足我们对智能指针的需求。例如,auto_ptr不能用作STL容器的元素。Boost的智能指针类填充了标准所留下来的缺口。

本章主要关注 scoped_ptr, shared_ptr, intrusive_ptr, 和 weak_ptr. 虽然剩下的 scoped_array 和 shared_array 有时候也很有用,但它们用的不是很多,而且它们与已讨论的非常相近,这里就不重复讨论它们了。

Smart_ptr如何适应标准库?

Smart_ptr库已被提议包含进标准库中,主要有以下三个原因:

标准库现在只提供了一个auto_ptr, 它仅是一类智能指针,仅仅覆盖了智能指针族谱中的一个部分。shared_ptr 提供了不同的,也是更重要的功能。

Boost的智能指针专门为了与标准库良好合作而设计,并可作为标准库的自然扩充。例如,在 shared_ptr之前,还没有一个标准的智能指针可用作容器的元素。

长久以来,现实世界中的程序员已经在他们的程序中大量使用这些智能指针类,它们已经得到了充分的验证。

以上原因使得Smart_ptr库成为了C++标准库的一个非常有用的扩充。Boost.Smart_ptr的 shared_ptr (以及随同的助手 enable_shared_from_this) 和 weak_ptr 已被收入即将发布的Library Technical Report。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: