假设我需要为抽象基类及其派生类创建两个工厂(我无法访问实际的构造函数)。在效率和代码风格方面哪个是最好的结构?
1)让所有工厂返回shared_ptr。这是统一的,但导致派生类有许多不必要的shared_ptrs,因为它们在客户端代码中被直接取消引用。
std::shared_ptr<Derived> createDerived(Argument arg)
{
return std::make_shared<Derived>(arg);
}
std::shared_ptr<AbstractBaseClass> createABC(Argument arg)
{
if (suchAndSo(arg))
return createDerived(arg);
else
return nullptr; // or createSomeOtherDerivedClass
}
int main()
{
Argument Arg;
Derived d = *createDerived(arg);
auto pAbc = createABC(arg);
}
2)让派生类的工厂返回一个值,让ABC工厂返回一个共享的ptr,它是用make_shared和Derived的复制构造函数构造的(导致许多复制构造函数调用)
Derived createDerived(Argument arg)
{
return Derived(arg);
}
std::shared_ptr<AbstractBaseClass> createABC(Argument arg)
{
if (suchAndSo(arg))
return make_shared<AbstractBaseClass>(createDerived(arg));
else
return nullptr; // or createSomeOtherDerivedClass
}
int main()
{
Argument Arg;
Derived d = createDerived(arg);
auto pAbc = createABC(arg);
}
答案 0 :(得分:3)
在ABC案例中,您只需返回unique_ptr
即可避免shared_ptr
的开销。但是,仅当~AbstractBaseClass
为虚拟时才可以选择该选项。
通过返回unique_ptr
,允许调用者决定是否需要共享该对象。
当返回具体类型的对象时,返回值确实是一个很好的选择。这避免了动态分配的成本。
导致许多复制构造函数调用
如果对象不是可移动构造的,并且优化器没有实现复制省略(任何像样的优化器那样做),则返回工厂本身的值只会复制。
您可以实现返回工厂的抽象指针,而无需委托给返回工厂的值,而是直接构造对象以避免该副本(移动)。
答案 1 :(得分:0)
两个工厂函数都应该返回简单的指针。共享指针应该应用于他们的结果。
在逻辑上,使用工厂方法选择适当的构造函数与管理对象所有权(通过共享指针)不同。