如何证明 c++11 make_shared() 即使在 dtor 之后也能保持shared_ptr的控制块存活?



我的问题是:是否存在share_ptr ref计数为0,而weak_ptr ref计数器为而不是0的情况?

C++中make_shared和普通shared_ptr的差异

引用这个线程,表明如果一个shared_ptr是由make_shared创建的,并且有weak_ptr,那么它的控制块将是活动的until,shared_ptr和weak_ptr'的ref计数都为0。上面写着:

weak_ptrs必须有一种方法来确定托管对象是否仍然有效(例如锁定(。他们通过检查拥有托管对象的shared_ptr的数量来实现这一点,托管对象存储在控制块中。结果是控制块是活动的,直到shared_ptr计数和weak_ptr计数都达到0。


我做了一个快速测试。我希望make_shared创建的shared_ptr,如果有weak_ptr指向它,那么在shared_ptr被破坏后,它的control block仍然会持有某物。

#include<memory>
#include<iostream>
using namespace std;
struct My {
int m_i;
My(int i) : m_i(i) { cout << "My ctor:" << m_i << 'n';}
~My() { cout << "My ctor:" << m_i << 'n';}
};
weak_ptr<My> wp1, wp2;
int main() {
{
auto sp1 = shared_ptr<My>(new My(30));
wp1 = weak_ptr<My>(sp1);
}
cout<< wp1.use_count() << endl;
{
auto sp2 = make_shared<My>(40);
wp2 = weak_ptr<My>(sp2);
}
cout<< wp2.use_count() << endl;
return 0;
}

两个use_count都将打印0,我的程序似乎没有显示control blocks是否活着。

那么,我们如何证明The result is that the control blocks are alive until both shared_ptr and weak_ptr's ref count gets 0呢?

有任何可以测试/证明这一理论的示例代码吗?

这不是一个"理论";这需要是";"已证明";。这是真的法令;该标准要求CCD_ 10知道它们所链接的所有CCD_。这是weak_ptr::lock的要求所必需的。实现这一点的唯一可行方法(在不违反线程安全保证或以极其糟糕的方式提供它们的情况下(是拥有一块由弱指针和共享指针共同拥有的内存,只有在所有指针都被销毁时才会处理。

如果您希望看到这一演示,可以将用户定义的分配器类型传递给shared_ptr的构造函数。CCD_ 14将使用此来分配用于CCD_ 15的控制块。只有当最后一个共享指针或弱指针被销毁时,控制块才会被删除。您可以对allocate_shared执行同样的操作。

您的代码无法证明,因为sp1、sp2是局部变量,当它们超出范围时,它们将被释放。你可以用勾手或蛙跳来展示你想要看到的结果,但这并不容易。我们可以阅读weak_ptr的源代码,这样我们就可以知道真正的作用,weak_ptr的源代码太多了,我们只查看关键部分:

// The actual weak_ptr, with forwarding constructors and
// assignment operators.
template<typename _Tp>
class weak_ptr
: public __weak_ptr<_Tp>
{

};

从代码中,我们可以看到大多数工作都是由父类__weak_ptr完成的,即查看__weak_ptr的代码:

template<typename _Tp, _Lock_policy _Lp>
class __weak_ptr
{
public:


template<typename _Tp1>
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
{ __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }


long
use_count() const // never throws
{ return _M_refcount._M_get_use_count(); }


_Tp*            _M_ptr;         // Contained pointer.
__weak_count<_Lp>  _M_refcount;    // Reference counter.
};

当我们调用weak_ptr的use_count((时,我们调用_M_refcount_M_get_use_count((,_M_refcount是在类__weak_ptr的构造函数中分配的,在分配列表中我们可以看到_M_refcunt(__r._M_refccount(,所以我们应该知道__weak_count的构造函数中真正的作用:

template<_Lock_policy _Lp>
class __weak_count
{
public:

__weak_count(const __shared_count<_Lp>& __r)
: _M_pi(__r._M_pi) // nothrow
{
if (_M_pi != 0)
_M_pi->_M_weak_add_ref();
}


long
_M_get_use_count() const // nothrow
{ return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }


private:
friend class __shared_count<_Lp>;

_Sp_counted_base<_Lp>*  _M_pi;
};

在类__weak_count的构造函数中,成员_M_pi是由shared_ptr的成员_M_pi分配的,我们查看函数_M_get_use_count((,当我们调用weak_ptr的use_count(。

让我们回到你的问题上来:;是否存在share_ptr引用计数为0,而weak_ptr引用数不为0的情况">

我认为用正常的方式写代码,答案是否定的!

相关内容

  • 没有找到相关文章

最新更新