从工厂返回时向上投射唯一ptr的正确方法 我在90年代学习C++,但从那时起就没有用过。我正在工作中维护的一个小图书馆里使用现代技术,试图赶上过去几十年。我遇到了这个文体问题,我想知道什么是现代共识

从工厂返回时向上投射唯一ptr的正确方法 我在90年代学习C++,但从那时起就没有用过。我正在工作中维护的一个小图书馆里使用现代技术,试图赶上过去几十年。我遇到了这个文体问题,我想知道什么是现代共识,c++,factory,unique-ptr,C++,Factory,Unique Ptr,我有一个纯虚拟基类base,有两个实现a和B。实现不在头文件中;他们的公共API完全是Base的一部分。我有工厂函数来构造它们,它们需要调用一个公共初始值设定项。这些类不支持复制,并且可以在它们的生命周期中更改所有者,因此我使用unique\u ptr来保持事物的正常 总之,这导致了一个有点尴尬的结构: unique_ptr<Base> rv = make_unique<A>(); 同样,我为自己添加了一些约束条件,以保持事物超级干净: 因为类A和B是实现细节,所以我

我有一个纯虚拟基类
base
,有两个实现
a
B
。实现不在头文件中;他们的公共API完全是
Base
的一部分。我有工厂函数来构造它们,它们需要调用一个公共初始值设定项。这些类不支持复制,并且可以在它们的生命周期中更改所有者,因此我使用
unique\u ptr
来保持事物的正常

总之,这导致了一个有点尴尬的结构:

unique_ptr<Base> rv = make_unique<A>();
同样,我为自己添加了一些约束条件,以保持事物超级干净:

  • 因为类
    A
    B
    是实现细节,所以我不让它们在外部可见
  • 因此,工厂函数需要返回一个
    unique\u ptr
    ,而不是
    unique\u ptr
构造这种东西的通常方法是什么

如果我想应用RVO,那么rv(AFAICT)需要有类型unique而不是unique

因为您实际上并没有返回或分配构造的对象(只是指向它的(唯一的)指针),所以RVO在这里是不相关的
unique_ptr
基本上是零开销,它是一个单指针(即一个寄存器)。它可能在C++抽象机器(STD:/UnQuyJ-PTR的构造函数/运算符)方面有所不同,但在实践中,这方面将不会产生影响。 更重要的是:无论是否使用(N)RVO,都不会调用(move)赋值运算符或A或B的move/copy构造函数


请注意,这并不特定于
unique\u ptr
——如果要返回原始指针,同样的想法也适用。

您的设计很好。但是,如果您希望消除返回时的移动/复制(您的设计就是这样)(当然,如果您的编译器支持这样的优化),那么您可能还希望在创建站点上消除它。为此,您需要使用

std::unique_ptr<Base> rv(new Derived(...));
std::unique_ptr rv(新派生的(…);
在这里,你应该注意你的位置,而不是省略号。关于您的注释,在现代C++中,使用<代码>新< /代码>是如何使用它的。它不是,见,<代码> MaxIOxION//COD>内部使用<代码>新< /代码>,它是用现代C++编写的。
但同样,你的设计很好,只有在你真的想避免搬家的情况下,你才可以求助于我的建议。

所有这些看起来都很好。
rv
的类型无关紧要,你将有
搬家
。如果初始化时出现
unique\u ptr
,如果返回时出现
unique\u ptr
。但是如果使用
unique\u ptr(新派生(…)
,mmm。。。为什么不想用它呢?@约拉:我不想使用<代码> UnQuyjpTR(new派生(…))< /C> >,因为它不例外,因此在现代C++中是不鼓励的。另请参见和。我没有描述
A()
构造函数的详细信息。特别是,我没有说它是否会抛出异常。这就是 UnQuyjpTR(new派生(…))< /> >在C++中至少会被阻止的主要原因,至少是C++ 14之后:如果派生(…)>代码>构造函数可以抛出,那么最终会泄漏内存和潜在的其他资源。更多信息,请参见我之前回复中的链接。我意识到,作为一个单词,
unique\u ptr
非常便宜,而原始指针也同样便宜。我试图将其推广到移动构造函数更昂贵的其他仅移动类,这样我就可以练习编写NRVO友好函数。换言之,假设我有一个更昂贵的类,而不是
unique\u ptr
。@Piquan在这种情况下,用这些类的示例来说明这个问题会很有帮助。“imagine
unique\u ptr
要昂贵得多”这一假设很难讨论,因为“只移动从工厂返回但不是多态性(即不是指针或围绕它的薄型包装)的类是昂贵的”,这似乎不是一个合理的设计(但在多个级别上是矛盾的)。如果你有一个具体的案例,那么我们可以对此进行推理——我怀疑解决方案不是RVO,而是设计变更。
std::unique_ptr<Base> rv(new Derived(...));