-->

如何做一个weak_ptr的知道,共享资源已经过期?(How does a weak_ptr kno

2019-07-17 13:58发布

考虑下面的代码:

#include <memory>
#include <iostream>

using namespace std;

struct MySharedStruct
{
  int i;
};

void print_value_of_i(weak_ptr<MySharedStruct> weakPtr)
{
  if (shared_ptr<MySharedStruct> sp = weakPtr.lock())
  { cout << "Value of i = " << sp->i << endl; }
  else
  { cout << "Resource has expired"; }
}

int main()
{
  shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct() );
  sharedPtr->i = 5;

  weak_ptr<MySharedStruct> weakPtr;
  weakPtr = sharedPtr;

  print_value_of_i(weakPtr);

  sharedPtr.reset(new MySharedStruct() ); // <<----- How does weak_ptr know it has expired after this line executes?
  sharedPtr->i = 10;

  print_value_of_i(weakPtr);

  return 0;
}

请问该怎么做weak_ptr知道它已过期考虑到资源shared_ptr是引用已经基本上是由另一个资源替代? 什么weak_ptr跟踪就知道肯定是共享资源被破坏和新的共享资源取代? 的方法,例如实施例定义(如果相关的话) lockweak_ptr将不胜感激。

Answer 1:

当所分配的控制块shared_ptr从一个普通的指针创建包含用于对象和两个基准计数器的指针对象本身和定制删除对象(如有)。 当参考计数器达到零的对象被释放,并且将指针设置为空。 所以,当对象的引用计数为零,这意味着该物体消失。

对于x86和x86-64他们使用原子操作,并没有明确的锁定(无互斥体或自旋锁)。 实施的关键是功能的特殊无锁(繁忙的旋代码语言) atomic_conditional_increment仅如果不是零递增对象引用计数器。 它在实现中使用weak_ptr::lock功能,以应付比赛时,多个线程试图创建一个shared_ptr来自同一weak_ptr使用对象的引用计数为零。 见http://www.boost.org/doc/libs/1_52_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp

控制块本身之间共享shared_ptr的和weak_ptr的和为自己的另一个参考计数器,以便直到它的最后一个引用被释放它保持活着。

shared_ptr被重新分配它指向另一个控制块,使得一个控制块只有永远指向一个相同的对象。 换句话说,没有替换一个对象与另一个在控制块。



Answer 2:

简答

我怀疑大多数实现通过具有共享控制块既实现这一weakPtrsharedPtr参考。 当sharedPtr复位时,它递减一个use_count ,所述控制块weakPtr可以使用以测试是否指针是有效的。

长一点的回答

但我认为,可以根据具体实现而变化。 这里有一个窜吹的C ++ 11个标准应该发生的事情说:

shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct());

20.7.2.2.1, sharedPtr构造与给定数据的所有权。

weak_ptr<MySharedStruct> weakPtr;
weakPtr = sharedPtr;

20.7.2.3.1, weakPtr被构造和然后被分配的值sharedPtr 。 转让后, weakPtrsharedPtr现在分享给定数据的所有权。

sharedPtr.reset(new MySharedStruct());

20.7.2.2.4, reset(Y*)等价于shared_ptr(Y*).swap(*this) 。 换句话说, sharedPtr交换与临时内容shared_ptr拥有新的数据。

在交换之后, sharedPtr将拥有新的数据,并临时将共享旧的数据与所有权weakPtr

20.7.2.2.2,临时然后破坏:

  • 由于临时拥有旧数据和不共享与其他所有权shared_ptr实例,它删除旧数据。
  • 共享与临时所有权所有实例shared_ptr将报告use_count()比其先前的值减一。

这意味着, weakPtr.use_count() == 0

if (shared_ptr<MySharedStruct> sp = weakPtr.lock()) { 
  cout << "Value of i = " << sp->i << endl;
} else {
  cout << "Resource has expired"; 
}

20.7.2.3.5,呼吁lock相当于

expired() ? shared_ptr<T>() : shared_ptr<T>(*this)

...和expired()相当于

use_count() == 0

...这意味着lock会返回一个空shared_ptr



文章来源: How does a weak_ptr know that the shared resources has expired?