shared_ptr

1简介编辑

shared_ptr是一种智能指针(smart
pointer)。

2作用编辑

shared_ptr的作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference
counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。这在非环形数据结构中防止资源泄露很有帮助。
auto_ptr由于它的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在标准容器中;如果我们希望当容器析构时能自动把它容纳的指针元素所指的对象删除时,通常采用一些间接的方式来实现,显得比较繁琐。boost库中提供了一种新型的智能指针shared_ptr,它解决了在多个指针间共享对象所有权的问题,同时也满足容器对元素的要求,因而可以安全地放入容器中。

3历史编辑

shared_ptr最初实现于Boost库中,后来被C++标准委员会收录于TR1技术报告中,成为C++0x的一部分。 

4概要编辑

namespace boost {
class bad_weak_ptr: public std::exception;
template<class T> class weak_ptr;
template<class T> class shared_ptr {
public:
typedef T element_type;
shared_ptr(); // never throws
template<class Y> explicit shared_ptr(Y * p);
template<class Y, class D> shared_ptr(Y * p, D d);
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
~shared_ptr(); // never throws
shared_ptr(shared_ptr const & r); // never throws
template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws
template<class Y> explicit shared_ptr(weak_ptr<Y>
const & r);
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
shared_ptr & operator=(shared_ptr const & r); // never throws
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
void reset(); // never throws
template<class Y> void reset(Y * p);
template<class Y, class D> void reset(Y * p, D d);
template<class Y, class D, class A> void reset(Y * p, D d, A a);
template<class Y> void reset(shared_ptr<Y> const & r, T * p); // never throws
T & operator*() const; // never throws
T * operator->() const; // never throws
T * get() const; // never throws
bool unique() const; // never throws
long use_count() const; // never throws
operator unspecified-bool-type() const; // never throws
void swap(shared_ptr & b); // never throws
};
template<class T, class U>
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
template<class T, class U>
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
template<class T> T * get_pointer(shared_ptr<T> const & p); // never throws
template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
template<class E, class T, class Y>
std::basic_ostream<E, T> & operator<<(std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
template<class D, class T>
D * get_deleter(shared_ptr<T> const & p);
}[1]

5用法编辑

删除共享对象

使用shared_ptr解决的主要问题是知道删除一个被多个客户共享的资源的正确时机。下面是一个简单易懂的例子,有两个类 A和 B, 它们共享一个int实例。使用 boost::shared_ptr,
你需要必须包含 "boost/shared_ptr.hpp".
#include "boost/shared_ptr.hpp"
#include <cassert>
class A {
boost::shared_ptr<int> no_;
public:
A(boost::shared_ptr<int> no) : no_(no) {}
void value(int i) {
*no_=i;
}
};
class B {
boost::shared_ptr<int> no_;
public:
B(boost::shared_ptr<int> no) : no_(no) {}
int value() const {
return *no_;
}
};
int main() {
boost::shared_ptr<int> temp(new int(14));
A a(temp);
B b(temp);
a.value(28);
assert(b.value()==28);
} 类 A和 B都保存了一个 shared_ptr<int>. 在创建 A和 B的实例时,shared_ptr temp被传送到它们的构造函数。这意味着共有三个 shared_ptr:a,
b, 和 temp,它们都引向同一个int实例。如果我们用指针来实现对一个的共享,A和 B必须能够在某个时间指出这个int要被删除。在这个例子中,直到main的结束,引用计数为3,当所有 shared_ptr离开了作用域,计数将达到0,而最后一个智能指针将负责删除共享的
int.

标准容器

把对象直接存入容器中有时会有些麻烦。以值的方式保存对象意味着使用者将获得容器中的元素的拷贝,对于那些复制是一种昂贵的操作的类型来说可能会有性能的问题。此外,有些容器,特别是 std::vector, 当你加入元素时可能会复制所有元素,这更加重了性能的问题。最后,传值的语义意味着没有多态的行为。如果你需要在容器中存放多态的对象而且你不想切割它们,你必须用指针。如果你用裸指针,维护元素的完整性会非常复杂。从容器中删除元素时,你必须知道容器的使用者是否还在引用那些要删除的元素,不用担心多个使用者使用同一个元素。这些问题都可以用shared_ptr来解决。
下面是如何把共享指针存入标准库容器的例子。
#include "boost/shared_ptr.hpp"
#include <vector>
#include <iostream>
class A {
public:
virtual void sing()=0;
protected:
virtual ~A() {};
};
class B : public A {
public:
virtual void sing() {
std::cout << "Do re mi fa so la";
}
};
boost::shared_ptr<A> createA() {
boost::shared_ptr<A> p(new B());
return p;
}
int main() {
typedef std::vector<boost::shared_ptr<A> > container_type;
typedef container_type::iterator iterator;
container_type container;
for (int i=0;i<10;++i) {
container.push_back(createA());
}
std::cout << "The choir is gathered: \n";
iterator end=container.end();
for (iterator it=container.begin();it!=end;++it) {
(*it)->sing();
}
} 这里有两个类, A和 B, 各有一个虚拟成员函数 sing. B从 A公有继承而来,并且如你所见,工厂函数 createA返回一个动态分配的B的实例,包装在shared_ptr<A>里。在 main里, 一个包含shared_ptr<A>的 std::vector被放入10个元素,最后对每个元素调用sing。如果我们用裸指针作为元素,那些对象需要被手工删除。而在这个例子里,删除是自动的,因为在vector的生存期中,每个shared_ptr引用计数都保持为1;当
vector被销毁,所有引用计数器都将变为零,所有对象都被删除。有趣的是,即使 A的析构函数没有声明为 virtual, shared_ptr也会正确调用
B的析构函数!
上面的例子示范了一个强有力的技术,它涉及A里面的protected析构函数。因为函数 createA返回的是 shared_ptr<A>, 因此不可能对shared_ptr::get返回的指针调用
delete。这意味着如果为了向某个需要裸指针的函数传送裸指针而从shared_ptr中取出裸指针的话,它不会由于意外地被删除而导致灾难。那么,又是如何允许 shared_ptr删除它的对象的呢?
这是因为指针指向的真正类型是 B; 而B的析构函数不是protected的。这是非常有用的方法,用于给shared_ptr中的对象增加额外的安全性。
转自:
1 百度百科
2 http://blog.csdn.net/sndaxdrs/article/details/6175701

boost库之shared_ptr的更多相关文章

  1. boost库之 shared_ptr学习笔记

  2. (六)boost库之内存管理shared_ptr

    (六)boost库之内存管理shared_ptr 1.shared_ptr的基本用法 boost::shared_ptr<int> sp(new int(10)); //一个指向整数的sh ...

  3. 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)

    一.boost 智能指针 智能指针是利用RAII(Resource Acquisition Is Initialization:资源获取即初始化)来管理资源.关于RAII的讨论可以参考前面的文章.在使 ...

  4. boost库----enable_shared_from_this类的作用和实现原理

    使用boost库时,经常会看到如下的类 class A:public enable_share_from_this<A> 在什么情况下要使类A继承enable_share_from_thi ...

  5. boost库在工作(37)网络UDP服务端之七

    前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...

  6. boost库在工作(39)网络UDP异步服务端之九

    前面创建的UDP服务器和客户端,都是同步的方式,也就是说当接收数据时,不能参与别的事情执行的.如果在一个只有界面线程的程序里,又不想创建多线程,导致复杂程度的增加,在这种情况之下,我们还有一个方案可以 ...

  7. boost库的安装,使用,介绍,库分类

    1)首先去官网下载boost源码安装包:http://www.boost.org/ 选择下载对应的boost源码包.本次下载使用的是 boost_1_60_0.tar.gz (2)解压文件:tar - ...

  8. Boost源代码学习---shared_ptr.hpp

    最近观看Boost库源代码.Boost功能强大的库,但它的许多源代码,十一细读太费时间,毕竟,还有其他东西要学.所以我决定脱脂感兴趣的章节,他们的设计思路和难以理解的地方记录. shared_ptr是 ...

  9. 比特币源码分析--C++11和boost库的应用

    比特币源码分析--C++11和boost库的应用     我们先停下探索比特币源码的步伐,来分析一下C++11和boost库在比特币源码中的应用.比特币是一个纯C++编写的项目,用到了C++11和bo ...

随机推荐

  1. Validation of viewstate MAC failed machinekey生成、使用方法

    前段时间公司为了减轻服务器压力,对网页做了集群,分布在多台服务器,通过DNS轮回解析到各台服务器,结果页面只要打开停留到DNS解析到下一个地址,就会出现出下错误信息. Validation of vi ...

  2. 【贪心】 poj 1032 和为n的若干数最大乘积

    给出n,把n分解为若干不相同数之和,使之乘积最大.贪心,Discuss里面的思路:把n分解为从2开始的连续整数,如果有多,则从高位开始依次加1.如26,我们得到2+3+4+5+6,此时还剩余6(26- ...

  3. SEO策略与细节:细节决定成败

    昨天展开seo探讨会.听了一场医疗界seo大神的讲座.收益匪浅今天讲他的演讲内容整理出来与大家分享.希望对医疗界的seo带来些帮助.站长们一起成长! 一.首页 1.元标签设置 标题:上海癫痫病医院哪家 ...

  4. js 判断提交表单

    <SCRIPT language=javascript> function check_book() { if(document.form1.Username.value=="& ...

  5. 安卓开发-使用XML菜单布局简单介绍

    使用xml布局菜单   目前为止我们都是通过硬编码来增加菜单项的,android为此提供了一种更便利的方式,就是把menu也定义为应用程序的资源,通过android对资源的本地支持,使我们可以更方便地 ...

  6. java 数据结构 图

    以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客,主要是在自己理解的基础上进行记录. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示 ...

  7. HDU 1054 Strategic Game 最小点覆盖

     最小点覆盖概念:选取最小的点数覆盖二分图中的所有边. 最小点覆盖 = 最大匹配数. 证明:首先假设我们求的最大匹配数为m,那么最小点覆盖必然 >= m,因为仅仅是这m条边就至少需要m个点.然后 ...

  8. cocos2d-x 3.x随机数

    1.使用标准库std::rand()函数 rand();//产生0~RAND_MAX(0x7fff=32767)间的int类型随机数 rand()%;//产生0~5间的int类型随机数,不包括5 2. ...

  9. 转:浅谈手机app测试注意点

    现在我们测试时,开发会先在本地机上打好测试包,自己安装,轮完一轮,开发修改好后,再打一个包.以下是功能测试时需要注意的点: 1.登录 ●登录用户名和密码错误时,界面有提示信息 ●用户主动退出登录后,下 ...

  10. HDU 2444 The Accomodation of Students

    首先是要构造二分图,然后二分图的最大匹配. 还有没完全证明过我的方法的正确性,但是AC了..... #include<cstdio> #include<cstring> #in ...