能否将栈/全局变量传入接受std::shared_ptr的函数?自定义实现是否有风险?
该实现存在多处潜在风险与设计冗余,具体如下:
1. 公有继承std::shared_ptr隐含未定义行为
std::shared_ptr的析构函数不是虚函数,如果代码中出现基类指针指向派生类实例后执行delete的操作,会直接触发未定义行为,派生类部分无法被正确析构。即便你的派生类没有额外成员、当前测试未暴露问题,这也属于违反C++设计规范的实现。
实际上你完全不需要自定义派生类,直接使用std::shared_ptr原生的支持自定义删除器的构造函数即可实现完全相同的效果,没有任何继承必要:
// 原生shared_ptr即可实现无操作删除逻辑,无需自定义派生类 std::shared_ptr<T> stack_ptr(target, [](T* /* unused */) {});
2. 贴出的代码存在语法错误
你给出的示例代码末尾多写了一个多余的};,类定义结束仅需要一组闭合大括号加分号,能正常编译运行应该是实际编写时修正了这个笔误。
3. 使用场景存在隐性未定义行为风险
该实现仅保证了智能指针引用计数归零时不释放目标内存,但没有任何机制约束传入的栈变量/全局变量的生命周期长于所有持有该智能指针的对象。如果接收std::shared_ptr的函数将指针持久化存储,在栈变量弹出销毁、全局变量析构之后再访问指针,就会触发野指针访问,属于典型的未定义行为。
4. 空删除器可能不符合部分场景需求
你当前使用的空删除器不会执行目标对象的析构函数,如果T类型的析构函数包含内存释放之外的逻辑(比如释放文件句柄、归还互斥锁、刷写IO缓冲区等),会导致这部分逻辑丢失,引发资源泄漏。
注意:如果你的场景需要执行析构逻辑但不释放内存(比如目标对象在自定义申请的堆内存上构造),可以将删除器改为
[](T* p) { p->~T(); };但该写法绝对不能用于栈/全局变量,否则栈弹出、程序退出时对象析构函数会被二次调用,直接触发未定义行为。
内容的提问来源于stack exchange,提问作者rileymat
相关产品推荐
相关产品推荐

