如何为自定义函数创建std::shared_ptr类型的智能指针?
给函数指针创建智能指针的正确姿势
嘿,先给你掰明白一个核心点:std::shared_ptr这类智能指针本来是用来管理动态分配的内存(比如new出来的对象)的,而函数本身存在程序的代码段里,根本不需要我们手动释放内存,所以其实大部分场景下,完全没必要用智能指针去管理函数指针。不过如果你确实有特殊需求(比如要把函数指针塞进要求智能指针的容器里),那咱们可以这么搞:
1. 直接用shared_ptr管理函数指针(必须自定义删除器!)
默认的shared_ptr会在最后调用delete去释放指针,但函数指针可不能被delete,一删就崩了!所以必须给它配个啥也不干的删除器:
#include <memory> double returnValue(int i){ return i; } int main() { // 先给函数指针整个别名,写起来方便 using FuncPtr = double(*)(int); // 创建shared_ptr,第二个参数就是空删除器——啥也不做 std::shared_ptr<void> func_ptr(&returnValue, [](void*) {}); // 要调用的话,得把void*转回到原来的函数指针类型 auto call_func = static_cast<FuncPtr>(func_ptr.get()); double res = call_func(5); // 这里会得到5.0 return 0; }
这里用std::shared_ptr<void>是因为函数指针类型没法直接当shared_ptr的模板参数(shared_ptr默认要求模板类型是可被delete的,函数指针不符合),所以转成void*绕一下,再靠自定义删除器避免错误操作。
2. 封装成可调用对象(更优雅的玩法)
如果只是想要类似智能指针的共享语义,不如把函数包成一个无状态的可调用对象,再用shared_ptr管这个对象,这更符合智能指针的设计初衷:
#include <memory> double returnValue(int i){ return i; } // 把函数包进一个结构体里,重载()运算符 struct FuncWrapper { double operator()(int i) const { return returnValue(i); } }; int main() { // 直接make_shared创建这个封装对象 auto func_ptr = std::make_shared<FuncWrapper>(); double res = (*func_ptr)(5); // 直接调用就行 return 0; }
为啥你之前的尝试失败了?
你用auto someptr = std::make_shared<double>(&returnValue);的时候,std::make_shared<double>是用来创建一个double类型的对象,并用你传的参数去初始化它——但你传的是函数指针,这就会把函数指针的地址强行转成double值,完全不是你要的“管理函数指针”的效果,当然会失败啦。
最后总结下:如果不是非用不可,直接用原始函数指针就够了;真要上智能指针,要么自定义删除器,要么封装成可调用对象~
内容的提问来源于stack exchange,提问作者KKMKK
相关产品推荐
相关产品推荐

