结合自定义释放操作使用std::unique_ptr的类改写正确性问询
如何用
std::unique_ptr替换类中的原始指针并自定义释放函数? 我有一个包含构造函数和析构函数的propagation_module类,代码如下:
class propagation_module{ private: gsl_interp_accel *xa; interp2d_spline *interp_s; public: propagation_module() { std::vector<int> p_N = {1, 2, 3}, z_vec = {1, 2, 3}; xa = gsl_interp_accel_alloc(); interp_s = interp2d_spline_alloc(interp2d_bicubic, p_N.size(), z_vec.size()); } ~propagation_module(){ gsl_interp_accel_free(xa); interp2d_spline_free(interp_s); } };
我希望将类中的原始指针替换为std::unique_ptr变量,但不清楚如何实现自定义释放函数。参考其他问题后,我写出了如下改写代码:
class propagation_module { private: std::unique_ptr<gls_interp_accel, decltype(&gsl_interp_accel_free)> xa; std::unique_ptr<interp2d_spline, decltype(&interp2d_spline_free)> interp_s; public: propagation_module() { //与上述构造函数逻辑相同 } //无需析构函数 };
请问该写法是否正确,我是否遗漏了什么?
你的核心思路是对的:用std::unique_ptr接管原始指针的生命周期,用自定义删除器替代手动编写析构函数,但当前写法存在几个需要修正的细节,我来逐一说明:
1. 先修正拼写错误
你把gsl_interp_accel误写成了gls_interp_accel,这个笔误会直接导致编译失败,先把这个错误改掉。
2. 必须正确初始化带自定义删除器的unique_ptr
你声明了带删除器的unique_ptr成员,但没有在构造函数中完成正确初始化——unique_ptr的默认构造只会生成空指针,不会自动绑定删除器和分配的指针。这里有两种常用的正确初始化方式:
方式一:构造函数初始化列表+reset
在初始化列表里先绑定删除器,再用reset方法替换为实际分配的指针:
class propagation_module { private: std::unique_ptr<gsl_interp_accel, decltype(&gsl_interp_accel_free)> xa; std::unique_ptr<interp2d_spline, decltype(&interp2d_spline_free)> interp_s; public: propagation_module() : xa(nullptr, &gsl_interp_accel_free), interp_s(nullptr, &interp2d_spline_free) { std::vector<int> p_N = {1, 2, 3}, z_vec = {1, 2, 3}; xa.reset(gsl_interp_accel_alloc()); interp_s.reset(interp2d_spline_alloc(interp2d_bicubic, p_N.size(), z_vec.size())); } };
方式二:用类型别名简化代码
如果觉得decltype(&xxx_free)写起来繁琐,可以提前定义类型别名,让代码更清爽:
// 提前定义带自定义删除器的unique_ptr类型 using GslAccelPtr = std::unique_ptr<gsl_interp_accel, decltype(&gsl_interp_accel_free)>; using Interp2dSplinePtr = std::unique_ptr<interp2d_spline, decltype(&interp2d_spline_free)>; class propagation_module { private: GslAccelPtr xa; Interp2dSplinePtr interp_s; public: propagation_module() : xa(gsl_interp_accel_alloc(), &gsl_interp_accel_free), interp_s(interp2d_spline_alloc(interp2d_bicubic, 3, 3), &interp2d_spline_free) { std::vector<int> p_N = {1, 2, 3}, z_vec = {1, 2, 3}; // 如果需要根据vector动态调整大小,替换成reset即可: // interp_s.reset(interp2d_spline_alloc(interp2d_bicubic, p_N.size(), z_vec.size())); } };
3. 可选优化:用lambda作为删除器
如果你不想依赖函数指针的类型,也可以用无捕获lambda作为删除器,代码可读性会更好:
class propagation_module { private: std::unique_ptr<gsl_interp_accel, void(*)(gsl_interp_accel*)> xa{ nullptr, [](gsl_interp_accel* ptr){ gsl_interp_accel_free(ptr); } }; std::unique_ptr<interp2d_spline, void(*)(interp2d_spline*)> interp_s{ nullptr, [](interp2d_spline* ptr){ interp2d_spline_free(ptr); } }; public: propagation_module() { std::vector<int> p_N = {1, 2, 3}, z_vec = {1, 2, 3}; xa.reset(gsl_interp_accel_alloc()); interp_s.reset(interp2d_spline_alloc(interp2d_bicubic, p_N.size(), z_vec.size())); } };
总结
你的方向是对的,修正拼写错误和初始化问题后,就可以完全依赖std::unique_ptr自动管理内存,不需要再手动编写析构函数,也能避免内存泄漏的风险。
内容的提问来源于stack exchange,提问作者arc_lupus
相关产品推荐
相关产品推荐

