c++ - std::shared_ptr 控制 block 中的虚函数

标签 c++ templates shared-ptr virtual-functions

shared::ptr我发现的实现是这样写的

namespace detail {
   struct deleter_base {
      virtual ~deleter_base() {}
      virtual void operator()( void* ) = 0;
   };
   template <typename T>
   struct deleter : deleter_base {
      virtual void operator()( void* p ) {
         delete static_cast<T*>(p);
      }
   };
}
template <typename T>
class simple_ptr {
   T* ptr;
   detail::deleter_base* deleter;
public:
   template <typename U>
   simple_ptr( U* p ) {
      ptr = p;
      deleter = new detail::deleter<U>();
   }
   ~simple_ptr() {
      (*deleter)( ptr );
      delete deleter;
   }
};

我的问题是

1) 为什么我们需要这样的结构(我的意思是类似于类型删除技术),难道我们不能把它作为删除器(见下面的代码)吗?在这里有一个虚拟函数的目的是什么,据我所知,如果它不是虚拟的,它无论如何都会调用 delete在正确的类型上(即在 Bar 上键入 std::shared_ptr<Foo>(new Bar) ),因为 simple_ptr具有模板化构造函数。

template <typename T>
   struct deleter {
      void operator()( void* p ) {
         delete static_cast<T*>(p);
      }
   };

2) 为什么我们需要在基类中使用虚析构函数?仅仅是因为它包含一个虚函数还是我们的删除器也必须有虚析构函数?

最佳答案

共享指针类型删除破坏,因为它们已经必须处理引用计数。一路打到删除破坏并没有那么昂贵。

如果您希望能够将指向 T 的共享指针转换为指向 void 的共享指针,则需要类型删除销毁,这有时很有用。通常,它不需要您存储的数据具有虚拟析构函数。

此外,它允许别名共享指针指向共享指针拥有的资源

你的删除器显然不起作用;由于它缺少一个公共(public)基类,它只能被普遍存储在 void* 中。 , 你不能调用 void*(ptr) .

忽略你的 shared::ptr ,如果我们看工业质量std::shared_ptr ,我们发现引用控制 block 在其末尾存储了类型删除的删除器,如果你 make_shared它用对象的实例替换类型删除的删除器。

struct rc_block {
  std::atomic<std::size_t> strong;
  std::atomic<std::size_t> weak;
  virtual void cleanup() = 0;
  virtual ~rc_block() {}
};

template<class T>
struct maked_rc_block final {
  std::atomic<std::size_t> strong = 1;
  std::atomic<std::size_t> weak = 0;
  std::aligned_storage<sizeof(T), alignof(T)> t;
  template<class... Args>
  maked_rc_block(Args&&...args) {
    ::new( (void*)&t ) T(std::forward<Args>(args)...);
  }
  void cleanup() override {
    ((T*)&t)->~T();
  }
};

template<class F>
struct action_rc_block final {
  std::atomic<std::size_t> strong = 1;
  std::atomic<std::size_t> weak = 0;
  F f;
  void cleanup() { f(); }
  template<class IN>
  actoin_rc_block(IN&& in):f(std::forward<IN>(in)) {}
};
template<class F>
action_rc_block(F)->action_rc_block<F>;

template<class T>
struct simple_shared {
  T* ptr = 0;
  rc_block* counters = 0;
  simple_shared( simple_shared const& o ):
    ptr(o.ptr), counters(o.counters)
  { if (counters) ++(counters->strong); }
  ~simple_shared() {
    if (counters && --(counters->strong)) {
      delete counters;
    }
  }
  template<class U>
  simple_shared(U* in):
    ptr(in),
    counters( new action_rc_block{[in]{ delete in; }} )
  {}
  // explicit deleter
  template<class U, class D>
  simple_shared(U* in, D&& d):
    ptr(in),
    counters( new action_rc_block{[in,d=std::forward<D>(d)]{ d(in); }} )
  {}
  template<class U, class V>
  simple_shared(simple_shared<U> const& alias_this, V* v):
    ptr(v),
    counters(alias_this.counters)
  {
    if(counters) ++(counters->strong);
  }
  template<class U>
  simple_shared( maked_rc_block<U>* c ):
    ptr( c?(T*)&c.t:nullptr ),
    counters(c)
  {}
};
template<class T, class...Args>
simple_shared<T> make_simple_shared( Args&&... args ) {
  auto* counter = new make_rc_block<T>( std::forward<Args>(args)... );
  return {counter};
}

我对原子的使用快速而松散,但我希望你明白这一点。

关于c++ - std::shared_ptr 控制 block 中的虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52955844/

相关文章:

c++ - Visual Studios 忽略文件

c++ - 如何调用带参数指针的函数指针?

c++ - 根据参数的积极性专门化模板

c++ - 包含它的模板化类型的 shared_ptr

c++ - "delete this"到一个用 std::shared_ptr 分配的对象?

c++ - 了解 range-v3 中的 zip 是如何工作的

c++ - 从字符串中提取字符

C++ 链表使用智能指针

c++ - 将方法的替代实现 (SFINAE) 移动到单独的文件

拥有对象的 C++ shared_ptr 调用析构函数