返回一个“指针”,该指针需要由智能指针持有。

9

我有一个项目,希望更多地使用智能指针。总体上,我已经成功实现了这个目标。然而,我遇到了一件事情,不确定什么是“最佳实践”。

基本上,我想从一个函数返回一个“指针”,但要求用户将其保存在智能指针中。不仅如此,我也不想强制使用特定的智能指针(比如shared vs. scoped)。

问题主要在于似乎没有一种合适的方法将scoped_ptr升级为shared_ptr(我认为这将是理想的解决方案)。我理解他们为什么不这样做,因为这将允许转移所有权,这可能会导致一些类似于std::auto_ptr的问题。

然而,在这种情况下,所有权的转移似乎是一个好主意。所以我的想法是这样的:

// contrived example of factory pattern
std::auto_ptr<A> func() { return std::auto_ptr<A>(new A); }

这个方法“可以”工作,因为scoped_ptrshared_ptr都有从std::auto_ptr中接管所有权的构造函数。

那么我的问题是,这种做法好吗?是否有更好的解决方案?我能想到的唯一替代方案是使用模板模板作为返回值,像这样:

// similar to above example
template <template <typename> class P>
P<A> func() { return P<A>(new A); }

这种方法看起来很有效,但是我认为需要一些工作才能使它与scoped_ptr一起使用。

你有什么想法吗?

3个回答

11

使用 std::auto_ptr 是一个好的实践,事实上 Bjarne Stroustrup 推荐了 这样的示例

auto_ptr 的移动语义为您处理它提供了正确的工具。

例如:

auto_ptr<Foo> make_foo()
{
    return auto_ptr<Foo>(new Foo);
}

Foo *raw_pointer=make_foo().release();
shared_ptr<Foo> shared_pointer=make_foo();
auto_ptr<Foo> auto_pointer=make_foo();
如果你返回一个 shared_ptr,你不能回退到普通指针;而使用 auto_ptr 则可以。你始终可以将 auto_ptr 升级为 shared_ptr,但反过来不行。
另一个重要的点是,shared_ptr 使用原子引用计数,这比 auto_ptr 所做的简单而完全有效的工作要慢得多。
附注:scoped_ptr 只是贫民版的 auto_ptr --- 它是不可复制的,也没有默认构造函数。与 shared_ptr 相比,“不那么混乱”的版本更像是 auto_ptr。一般来说,使用 scoped_ptr 没有太多优势。

单线程构建中的 shared_ptr 不使用原子引用计数。 - Mykola Golubyev
你是正确的,但默认情况下 boost 是构建多线程版本的。 - Artyom
2
使用scoped_ptr而不是auto_ptr的优点在于,当您想要明确指出不应该复制指针时,可以使用它。使用scoped_ptr时,您根本无法复制指针。这与您的示例使用auto_ptr和所有权转移一样,都是关于传达您的意图。 - Brian Neal
1
Scott Meyers在http://www.aristeia.com/Papers/resourceReturnProblem.txt上也有一篇非常详尽的文章。 - SCFrench

3
如果您建立了一个工厂,那么简单地返回指针就可以了。而您的工厂用户可以自行决定如何以及在哪里放置此指针。
如果您需要强制使用智能指针,那么您必须限制选择,因为您不希望他们使用“错误”的指针。
因此,使用boost::shared_ptr。但最好是将其typedef为MyClassPtr或MyClass::ptr。
尽管如此,工厂就像“new”。当我想要时,我会将new的结果放入std::auto_ptr中。但是当我不想使用智能指针时,我不想被迫每次都调用“release”。

是的,但如果可能的话,我想强制使用智能指针。 - Evan Teran
我同意,我们都是成年人了。返回一个裸指针,让代码的使用者决定如何最好地捕获返回值。我相信 shared_ptr 从 auto_ptr 构造函数将要被淘汰(auto_ptr 将被弃用)。 - Brian Neal
当auto_ptr在C++0x中被弃用时,unique_ptr将取而代之。我会转而返回unique_ptr。 - Aaron

1

使用C++11,您应该能够使用std::unique_ptr,因为其他智能指针类型都有构造函数,可以接受std::unique_ptr。如果您维护这些资源的内部列表,则可能需要使用std::shared_ptr


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接