C++ 如何在非模板类中存储函子?
我注意到,当我使用C++ 如何在非模板类中存储函子?,c++,c++11,storage,functor,C++,C++11,Storage,Functor,我注意到,当我使用std::shared_ptr(或任何其他智能指针)时,通过ctor分配一个自定义分配器/删除器,ctor恰好是一个模板。我的问题是:如何存储和使用分配器/删除器 这些函子是作为函数指针存储的,void*,还是什么?是间接通话还是直接通话 只是为了更清楚地了解我所要问的内容,请考虑下面的代码: struct SomethingAwesomeDeleter { public: void operator()(SomethingAwesome* ptr) const
std::shared_ptr
(或任何其他智能指针)时,通过ctor分配一个自定义分配器/删除器,ctor恰好是一个模板。我的问题是:如何存储和使用分配器/删除器
这些函子是作为函数指针存储的,void*
,还是什么?是间接通话还是直接通话
只是为了更清楚地了解我所要问的内容,请考虑下面的代码:
struct SomethingAwesomeDeleter
{
public:
void operator()(SomethingAwesome* ptr) const
{
// do something awesome
delete ptr;
}
};
typedef std::shared_ptr<SomethingAwesome> SomethingAwesomePtr;
SomethingAwesomePtr ptr{new SomethingAwesome, SomethingAwesomeDeleter{}};
struct SomethingAwesomeDeleter
{
公众:
void运算符()(SomethingAwesome*ptr)常量
{
//做些很棒的事
删除ptr;
}
};
typedef std::shared_ptr SomethingAwesomePtr;
SomethingAwesomePtr ptr{new SomethingAwesome,SomethingAwesomeDeleter{};
SomethingAwesomeDeleter{}
是如何存储和使用的
注意:
我确实意识到
std::shared\u ptr
是一个模板类,但是std::shared\u ptr
在类模板参数中没有用于删除器/分配器的模板参数,也就是说,没有像std::shared\u ptr
这样的模板类。您可以在std::function
中存储任何函数对象。这负责直接存储函数指针(如果它是普通函数)或将其包装到某个对象中。这是实现shared_ptr
deleter的一种可能方法,而不需要将函数类型作为模板类型的一部分
示例(未经测试,只是给你一个想法)
//这是实际保存共享指针的结构
//共享的\u ptr将引用此计数
模板
类共享\u ptr\u共享
{
std::函数del_;
T*p_;
//其他成员
模板
共享\u ptr\u共享(T*obj,Deleter-Deleter)
:p(p)
,del_(删除)
{
}
~shared\u ptr\u shared()
{
if(del_){
del_(p_);
}否则{
删除p_;
}
}
};
您可以在这里找到关于std::function的更多信息:没有您描述的模板类decl,您是正确的。但是
shared\u ptr
构造函数有这样一个模板覆盖(forshared\u ptr
有一大堆)。关于存储,我认为它是实现定义的,但我见过的大多数实现都将它们存储为shared_ptr的实例成员或类似的东西。在这一点上我可能(也可能是)错了,因为我不知道标准是否规定了上述对象的实际存储细节。换句话说,间接调用。嗯,我想这是我预料到的。是的,没有任何问题不能通过间接呼叫解决;)
// This is the struct which actually holds the shared pointer
// A shared_ptr would reference count this
template <typename T>
class shared_ptr_shared
{
std::function<void (T*)> del_;
T* p_;
// other members
template <typename Deleter>
shared_ptr_shared (T* obj, Deleter deleter)
: p_ (p)
, del_ (deleter)
{
}
~shared_ptr_shared ()
{
if (del_) {
del_ (p_);
} else {
delete p_;
}
}
};