boost库之shared_ptr

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值