c – 使用受保护的析构函数删除对象
作者:互联网
我必须为类编写一个共享指针,并且它必须做的许多其他事情是确保它可以删除它指向的对象.
如何编写可与具有受保护的析构函数的对象一起使用的解决方案?
另外,如果对象是使用placement new创建的,我不应该在对象上调用delete,因为该空间可能仍在使用(删除调用甚至可以工作吗?).我怎样才能发现这种情况?
规范的相关部分:
void reset();
The smart pointer is set to point to the null pointer. The reference count for the currently pointed to object, if any, is decremented.Sptr(); Constructs a smart pointer that points to the null pointer.
template <typename U>
Constructs a smart pointer that points to the given object. The reference count is initialized to one.
Sptr(U *);
Sptr(const Sptr &);
template <typename U> Sptr(const Sptr<U> &);
The reference count is incremented. If U * is not implicitly convertible to T *, this will result in a syntax error. Note that both the normal copy constructur and a member template copy constructor must be provided for proper operation.
调用代码的方式:
Sptr<Derived> sp(new Derived);
char *buf = (char *) ::operator new(sizeof(Sptr<Base1>));
Sptr<Base1> &sp2 = *(new (buf) Sptr<Base1>());
sp2 = sp;
sp2 = sp2;
sp.reset();
sp2.reset();
::operator delete(buf);
Base1拥有一切保护.
解决方法:
与引用计数器一起存储指向将删除对象的函数的指针(‘删除’).您将在智能指针的模板化构造函数中实例化删除器,您知道派生类型.这是一个非常天真的伪代码:
template<class T> void DefaultDeleter(void *p) { delete static_cast<T*>(p); }
struct ref_counter {
int refs;
void *p;
void (*d)(void *);
};
template<class T> class Sptr {
/* ... */
template <typename U> Sptr(U *p)
{
_c = new ref_counter;
_c->refs = 1;
_c->p = static_cast<void*>(p);
_c->d = &DefaultDeleter<U>;
_p = p;
}
T *_p;
ref_counter *_c;
};
当refs降至零时,调用(* _c-> d)(_ c-> p)来销毁指向的对象.
我当然假设Base的析构函数受到保护而Derived的析构函数是公共的,否则这个练习没有任何意义.
注意:这就是为什么std :: shared_ptr可以安全地与具有非虚析构函数的基类一起使用的原因.
标签:c,c11,shared-ptr 来源: https://codeday.me/bug/20190826/1725281.html