我的问题是:是否存在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的情况">
我认为用正常的方式写代码,答案是否定的!