如何让std::shared_ptr自动初始化为持有有效对象?
这个问题确实戳中了很多C++开发者的痛点——不小心声明了空的shared_ptr,后续使用时触发空指针错误。要从编译器层面强制实现默认初始化,而不是依赖开发者记得调用make_shared,这里有个很实用的方案:自定义一个包装std::shared_ptr的模板类,让它的默认构造函数自动创建对象实例。
自定义自动初始化的智能指针包装类
我们可以封装一个auto_shared_ptr模板,它继承自std::shared_ptr,但重写了默认构造函数,自动调用std::make_shared来初始化对象:
#include <memory> #include <utility> // 用于std::forward template <typename T> class auto_shared_ptr : public std::shared_ptr<T> { public: // 默认构造:自动创建T的默认构造实例 auto_shared_ptr() : std::shared_ptr<T>(std::make_shared<T>()) {} // 支持带参数的构造,转发参数给T的构造函数 template <typename... Args> explicit auto_shared_ptr(Args&&... args) : std::shared_ptr<T>(std::make_shared<T>(std::forward<Args>(args)...)) {} // 继承std::shared_ptr的所有其他构造函数(比如从原始指针、其他shared_ptr转换等) using std::shared_ptr<T>::shared_ptr; };
使用方式
- 声明时自动初始化默认构造的对象:
auto_shared_ptr<MyType> x; // 等价于std::shared_ptr<MyType> x = std::make_shared<MyType>(); - 需要带参数构造时,直接传递参数:
auto_shared_ptr<MyType> x(42, "hello"); // 调用MyType(int, const char*)构造函数 - 如果确实需要空指针,可以显式初始化:
auto_shared_ptr<MyType> x(nullptr); // 得到空的shared_ptr
额外优势
- 如果
MyType没有默认构造函数,auto_shared_ptr<MyType> x;会直接编译失败,避免了隐式的空指针风险——这反而帮你提前发现需要显式传递构造参数的场景。 - 完全兼容
std::shared_ptr的所有操作,因为我们继承了它的所有成员函数和构造逻辑,你可以把auto_shared_ptr当作std::shared_ptr来使用(比如传递给接受std::shared_ptr<T>的函数)。
辅助方案:编译器警告
如果你不想自定义类,也可以开启编译器的警告选项来提醒未初始化的shared_ptr:
- GCC/Clang:添加
-Wuninitialized或-Wmaybe-uninitialized - MSVC:添加
/W4或/w14700
不过这种方式只能给出警告,无法强制开发者修正,所以自定义包装类是更彻底的解决方案。
内容的提问来源于stack exchange,提问作者Jonn Dove
相关产品推荐
相关产品推荐

