enable_shared_from_this详解

东阳的学习笔记

shared_from_this()是C++多线程编程中经常会使用的到的一种方法。

问题提出:

见 linux 多线程服务器编程 P23. 如果 StockFactory 的生命期比 Stock 短,那么下列语句就会 core dump

// ...
pStock.reset(new Stock(key), 
		     boost::bind(&StockFactory::deleteStock, 
		     this, 
		     _1));
// ...

为了解决这个问题,我们似乎应该祭出惯用的 shared_ptr 大法, 问题来了:

如何获得一个指向当前对象的 shared_ptr 呢?

shared_from_this

enable_shared_from_this是一个类,将有上述需求的类继承自它,就可以解决上面所提出的问题。

enable_shared_from_this 有一个私有成员变量,保存了一个 weak_ptr指针, 可以看到其保存的就是 this

我们只需要将问题中的代码修改为下面的就可以解决问题了:

  1. 继承 enable_shared_from_this
  2. 在bind中使用
class StockFactory : public boost::enable_shared_from_this<StockFactory>, 
					 boost::noncopyable
{ /* ... */ }
pStock.reset(new Stock(key), 
		     boost::bind(&StockFactory::deleteStock, 
		     shared_from_this(), 
		     _1));

我们先来看看源码:

template<class T> class enable_shared_from_this
{
protected:
    BOOST_CONSTEXPR enable_shared_from_this() BOOST_SP_NOEXCEPT{}
    BOOST_CONSTEXPR enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT{}
    enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPT { return *this; }
     // ~weak_ptr<T> newer throws, so this call also must not throw
    ~enable_shared_from_this() BOOST_SP_NOEXCEPT{}
public:
    shared_ptr<T> shared_from_this()
    {
        shared_ptr<T> p( weak_this_ );
        BOOST_ASSERT( p.get() == this );
        return p;
    }

    shared_ptr<T const> shared_from_this() const
    {
        shared_ptr<T const> p( weak_this_ );
        BOOST_ASSERT( p.get() == this );
        return p;
    }

    weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPT
    {
        return weak_this_;
    }

    weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPT
    {
        return weak_this_;
    }

public: // actually private, but avoids compiler template friendship issues

    // Note: invoked automatically by shared_ptr; do not call
    template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPT
    {
        if( weak_this_.expired() )
        {
            weak_this_ = shared_ptr<T>( *ppx, py );
        }
    }

private:
    mutable weak_ptr<T> weak_this_;
};

但是,StockFactory的生命期似乎被意外延长了,不小于boost::function对象

弱回调

有时候我们需要“如果对象还活着,就调用它的成员函数,否则忽略之的语义”。
弱回调使用示例。(Factory通常是个 singleton,在程序正常运行期间不会销毁,这是只是为了展示弱回调的用法)

pStock.reset(new Stock(key),
             boost::bind(&StockFactory::weakDeleteCallback,
             boost::weak_ptr<StockFactory>(shared_from_this()),
             _1));
// 上面必须把 shared_from_this() 转型为 weak_ptr, 才不会延长生命期
// 因为 bind 绑定的是实参类型而不是形参类型

// ...

static void weakDeleteCallback(const boost::weak_ptr<StockFactory>& wkFactory, Stock *stock)
{
	shared_ptr<StockFactory> factory(wkFactory.lock());  // 尝试提升
	if (factory)    // 如果 factory 还在,那就清理stocks_
	{
		factory->removeStock(stock);
	}
	delete stock;  // sorry, i lied
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东阳z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值