Boost学习 (二)shared_ptr

本文深入探讨了C++中的shared_ptr智能指针,包括其构造函数、应用场景及如何使用定制删除器提高安全性。此外,还介绍了如何从this创建shared_ptr,以便更好地管理类实例。

       shared_ptr:

        template <class Y> explicit shared_ptr(const weak_ptr<Y>& r);

        从一个weak_ptr (本章稍后会介绍)构造shared_ptr。这使得weak_ptr的使用具有线程安全性,因为指向weak_ptr参数的共享资源的引用计数将会自增(weak_ptr不影响共享资源的引用计数)。如果weak_ptr为空 (r.use_count()==0), shared_ptr 抛出一个类型为bad_weak_ptr的异常。

template <typename Y> shared_ptr(std::auto_ptr<Y>& r);

        这个构造函数从一个auto_ptr获取r中保存的指针的所有权,方法是保存指针的一份拷贝并对auto_ptr调用release。构造后的引用计数为1。而r当然就变为空的。如果引用计数器不能分配成功,则抛出 std::bad_alloc 。


使用shared_ptr解决的主要问题是知道删除一个被多个客户共享的资源的正确时机。


#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);
}

         类 AB都保存了一个 shared_ptr<int>. 在创建AB的实例时,shared_ptr temp 被传送到它们的构造函数。这意味着共有三个shared_ptra,b, 和temp,它们都引向同一个int实例。如果我们用指针来实现对一个的共享,AB 必须能够在某个时间指出这个int要被删除。在这个例子中,直到main的结束,引用计数为3,当所有shared_ptr离开了作用域,计数将达到0,而最后一个智能指针将负责删除共享的int.



使用定制删除器的安全性

        我们已经看到对基类使用 protected 析构函数有助于增加使用shared_ptr的类的安全性。另一个达到同样安全级别的方法是,声明析构函数为 protected (或 private) 并使用一个定制删除器来负责销毁对象。这个定制删除器必须是它要删除的类的友元,这样它才可以工作。封装这个删除器的好方法是把它实现为私有的嵌套类,如下例所示:

#include "boost/shared_ptr.hpp"
#include <iostream>

class A {
  class deleter {
    public:
      void operator()(A* p) {
        delete p;
      }
  };
  friend class deleter;
public:

  virtual void sing() {
    std::cout << "Lalalalalalalalalalala";
  }

  static boost::shared_ptr<A> createA() {
    boost::shared_ptr<A> p(new A(),A::deleter());
    return p;
  }

protected:
  virtual ~A() {};
};

int main() {
  boost::shared_ptr<A> p=A::createA();
}

        注意,我们在这里不能使用普通函数来作为 shared_ptr<A> 的工厂函数,因为嵌套的删除器是A私有的。使用这个方法,用户不可能在栈上创建A的对象,也不可能对A的指针调用delete


从this创建shared_ptr

        有时候,需要从this获得 shared_ptr ,即是说,你希望你的类被shared_ptr所管理,你需要把"自身"转换为shared_ptr的方法。看起来不可能?好的,解决方案来自于我们即将讨论的另一个智能指针boost::weak_ptr.weak_ptrshared_ptr的一个观察者;它只是安静地坐着并看着它们,但不会影响引用计数。通过存储一个指向thisweak_ptr 作为类的成员,就可以在需要的时候获得一个指向thisshared_ptr。为了你可以不必编写代码来保存一个指向thisweak_ptr,接着又从weak_ptrshared_ptr得,Boost.Smart_ptr 为这个任务提供了一个助手类,称为enable_shared_from_this. 只要简单地让你的类公有地派生自enable_shared_from_this,然后在需要访问管理thisshared_ptr时,使用函数shared_from_this 就行了。下面的例子示范了如何使用enable_shared_from_this

#include "boost/shared_ptr.hpp"
#include "boost/enable_shared_from_this.hpp"

class A;

void do_stuff(boost::shared_ptr<A> p) {
  ...
}

class A : public boost::enable_shared_from_this<A> {
public:
  void call_do_stuff() {
    do_stuff(shared_from_this());
  }
};

int main() {
  boost::shared_ptr<A> p(new A());
  p->call_do_stuff();
}

        这个例子还示范了你要用shared_ptr管理this的情形。类 A 有一个成员函数 call_do_stuff 需要调用一个普通函数 do_stuff, 这个普通函数需要一个类型为boost:: shared_ptr<A>的参数。现在,在A::call_do_stuff里,this 不过是一个A指针, 但由于 A 派生自 enable_shared_from_this, 调用shared_from_this 将返回我们所要的shared_ptr 。在enable_shared_from_this的成员函数shared_from_this里,内部存储的weak_ptr 被转换为shared_ptr, 从而增加了相应的引用计数,以确保相应的对象不会被删除。

        线程函数中传入自身指针? 可以吗?


在以下情况时使用 shared_ptr

  • 当有多个使用者使用同一个对象,而没有一个明显的拥有者时

  • 当要把指针存入标准库容器时

  • 当要传送对象到库或从库获取对象,而没有明确的所有权时

  • 当管理一些需要特殊清除方式的资源时





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值