c++ - weak_ptr 如何知道共享资源已过期?

标签 c++ shared-ptr smart-pointers weak-ptr refcounting

考虑以下代码:

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

考虑到 shared_ptr 引用的资源基本上已被另一个资源替换,weak_ptr 如何知道它已过期? weak_ptr 跟踪什么以确保知道 old 共享资源已被销毁并被 new 共享资源替换? weak_ptr 中的 lock 等方法的示例定义(如果相关)将不胜感激。

最佳答案

shared_ptr 时分配的控制 block 是从一个普通指针创建的,该指针包含对象的引用计数器和指向对象本身的指针以及自定义删除器对象(如果有)。当该引用计数器达到零时,该对象将被释放并将指针设置为空。因此,当对象引用计数器为零时,意味着该对象已消失。

对于 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

控制 block 本身在shared_ptr之间共享的和weak_ptr的并且有另一个自己的引用计数器,因此它会一直存在直到最后一个对它的引用被释放。

shared_ptr被重新分配它指向另一个控制 block ,这样一个控制 block 只能指向一个相同的对象。换句话说,在控制 block 中没有一个对象被另一个对象替换。

关于c++ - weak_ptr 如何知道共享资源已过期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14043245/

相关文章:

c++ - 显式删除和新建 vs 使用 unique_ptr

c++ - 声明 2 数组时堆栈溢出

c++ - 在 C++ lambda 函数中捕获成员变量

c++ - weak_ptr 和父子循环依赖

C++ 依赖注入(inject)——通过引用还是通过 boost::shared_ptr?

c++ - 指向shared_ptr的不透明类型C指针

c++ - 如何判断哪个类拥有指针

c++ - 将空数据写入非阻塞套接字会导致 epoll_wait 挂起

c++ - 带有 C++ 的 OS X 中的 SIMD Sony vector 数学库

c++ - shared_ptr中weak_ptr的作用