3 回答
TA贡献1821条经验 获得超6个赞
是的,可以通过这种方式实现shared_ptr。Boost确实如此,并且C ++ 11标准也需要这种行为。作为一种附加的灵活性,shared_ptr不仅可以管理引用计数器。通常将所谓的删除器放入还包含引用计数器的同一存储块中。但有趣的是,此删除器的类型不是shared_ptr类型的一部分。这称为“类型擦除”,基本上与用于实现“多态函数” boost :: function或std :: function的技术相同,用于隐藏实际的仿函数的类型。为了使您的示例正常工作,我们需要一个模板化的构造函数:
template<class T>
class shared_ptr
{
public:
...
template<class Y>
explicit shared_ptr(Y* p);
...
};
因此,如果您将其与Base和Derived类一起使用,则...
class Base {};
class Derived : public Base {};
int main() {
shared_ptr<Base> sp (new Derived);
}
...具有Y = Derived的模板化构造函数用于构造shared_ptr对象。因此,构造函数有机会创建适当的删除对象和引用计数器,并将指向该控制块的指针存储为数据成员。如果参考计数器达到零,则将使用先前创建的可感知派生的删除器来处置该对象。
关于此构造函数(20.7.2.2.1),C ++ 11标准具有以下说法:
要求: p必须可转换为T*。Y应为完整类型。该表达式delete p应格式正确,行为应明确,并且不得抛出异常。
效果:构造一个shared_ptr对象是拥有指针p。
…
对于析构函数(20.7.2.2.2):
效果:如果*this为空或与另一个shared_ptr实例(use_count() > 1)共享所有权,则没有副作用。否则,如果*this拥有一个对象p和一个deleteer d,d(p)则被调用。 否则,如果*this拥有一个指针p,delete p则被调用。
(强调使用粗体是我的)。
TA贡献1846条经验 获得超7个赞
创建shared_ptr时,它将在内部存储一个删除程序对象。当shared_ptr将要释放所指向的资源时,将调用此对象。由于您知道如何在构造时销毁资源,因此可以对不完整的类型使用shared_ptr。谁创建了shared_ptr,谁在其中存储了正确的删除器。
例如,您可以创建一个自定义删除器:
void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.
shared_ptr<Base> p(new Derived, DeleteDerived);
p将调用DeleteDerived销毁指向的对象。该实现会自动执行此操作。
TA贡献1812条经验 获得超5个赞
只是,
shared_ptr 使用由构造函数创建的特殊删除函数,该函数始终使用给定对象的析构函数而不是Base的析构函数,这与模板元编程有关,但确实可行。
像这样
template<typename SomeType>
shared_ptr(SomeType *p)
{
this->destroyer = destroyer_function<SomeType>(p);
...
}
- 3 回答
- 0 关注
- 411 浏览
添加回答
举报