工厂方法返回 shared_ptr 是为了实现自动内存管理、支持共享所有权和多态性,避免内存泄漏并提升代码安全性与灵活性;通过 std::make_shared 创建对象可提高性能和异常安全性,适用于多模块共享对象或生命周期不确定的场景,尤其在需要将对象存入容器或传递给回调时比 unique_ptr 更合适,但需注意避免循环引用并保证注册机制的线程安全,是现代 c++++ 中构建可扩展系统的推荐做法。
在 C++ 的工厂模式中,使用智能指针(尤其是
std::shared_ptr
)作为返回类型是一种现代、安全且推荐的做法。相比传统的裸指针或
std::unique_ptr
,返回
shared_ptr
能更好地管理对象生命周期,避免内存泄漏,同时支持灵活的共享语义。
为什么工厂方法返回
shared_ptr
shared_ptr
?
工厂模式的核心是将对象的创建过程封装起来,客户端无需关心具体类型,只需通过接口使用对象。返回
shared_ptr
的主要优势包括:
- 自动内存管理:对象在不再被引用时自动释放,避免资源泄漏。
- 共享所有权:多个组件可以安全地共享同一个对象实例。
- 多态支持良好:
shared_ptr<Base>
可以持有派生类对象,适合多态场景。
- 与标准库和现代 C++ 代码兼容性好:比如可以轻松存入容器、传递给回调等。
工厂方法返回
shared_ptr
shared_ptr
的典型实现
假设我们有一个图形形状的基类和几个派生类:
#include <memory> #include <string> class Shape { public: virtual ~Shape() = default; virtual void draw() const = 0; }; class Circle : public Shape { public: void draw() const override { // 绘制圆形 } }; class Rectangle : public Shape { public: void draw() const override { // 绘制矩形 } };
接下来,我们实现一个工厂类或工厂函数,返回
std::shared_ptr<Shape>
:
#include
注册类型并使用:
// 注册类型 ShapeFactory::registerType("circle", []() { return std::make_shared<Circle>(); }); ShapeFactory::registerType("rectangle", []() { return std::make_shared<Rectangle>(); }); // 使用工厂创建对象 auto shape = ShapeFactory::create("circle"); if (shape) { shape->draw(); }
何时选择
shared_ptr
shared_ptr
而不是
unique_ptr
?
虽然
unique_ptr
更轻量、性能略优,但在以下场景中,
shared_ptr
是更合适的选择:
- 多个模块需要共享对象所有权。
- 对象可能被放入容器、回调、观察者列表等需要长期持有副本的地方。
- 工厂创建的对象生命周期不确定,且可能被多方引用。
如果你能确定对象只有一个所有者,且不会被共享,
unique_ptr
更高效。但在通用工厂中,尤其是框架或库代码中,
shared_ptr
更加灵活和安全。
注意事项与最佳实践
-
使用
make_shared
而不是直接
new
:
它更高效(一次内存分配),也更安全(避免异常时的内存泄漏)。 -
避免循环引用:
如果对象之间存在互相引用,注意使用weak_ptr
防止内存泄漏。
-
注册机制可扩展:
上述工厂支持运行时注册,适合插件式架构。 -
线程安全考虑:
如果多个线程同时调用create
,确保
creators()
的访问是线程安全的(首次初始化是安全的,但注册操作需加锁)。
基本上就这些。返回
shared_ptr
的工厂方法是现代 C++ 中构建可维护、可扩展系统的重要手段,尤其适用于需要多态和共享所有权的场景。
评论(已关闭)
评论已关闭