C++:访问shared_ptr容器应该返回原始指针还是shared_ptr?

3

如果我使用 shared_ptr 的容器并明确允许访问其元素,那么如果我希望容器负责“清理”,是应该返回 shared_ptr 还是原始指针?


class Container
{
private:
    std:vector<shared_ptr<Foo> > foo_ptrs;

public:
    shared_ptr<Foo> operator[](std::size_t index) const {}; // or
    Foo* operator[](std::size_t index) const {};
};

在这种情况下,返回shared_ptr有什么理由,还是原始指针可以吗?
问候!
3个回答

2
如果您想继续使用对象而不必担心容器元素被擦除,那么应该返回一个shared_ptr。否则,在其他容器用户清理容器或擦除您所引用的元素后,您可能会得到一个孤立的原始指针。请注意保留HTML标记。

即使容器存在的时间至少与使用指针的任何其他内容一样长(且不可能进行删除),也是如此吗? - jena
@jena - 在这种情况下,您应该可以放心使用原始指针。然而,假设往往会随着时间的推移而改变。 - Steve Townsend

2

返回引用

只有在你想让访问器共享生命周期管理时才返回shared_ptr。这是一种有效的设计,但正如你所说,Container负责清理。 shared_ptr只是Containter的实现细节,使用shared_ptrvector实现容器的事实不应该通过接口暴露出来。

除非从Container获取NULL有意义,否则不要返回指针。通常情况下,用户只想访问容器的第 i 个元素,而引用完美地完成了这项工作。

你真正需要的是一个std::vector<std::unique_ptr<Foo>>Container管理内存并在成员声明中说明了这一点。其他人没有必要知道实现细节。

如果你不愿意或无法使用C++0x,请查看Boost.Pointainers


感谢清晰的解释,boost的指针容器看起来不错。然而,我自己漏掉了一个要点:在需要存储多态基类容器中的类型的情况下,引用是行不通的...猜想这必须以不同的方式处理。 - jena
1
@jena: 为什么在这种情况下引用不起作用?一个指向基类的引用可以绑定到派生对象,就像一个指向基类的指针可以指向派生对象一样。这是相同的多态性。 - Steve Jessop
如果我想要在同一个容器中存储不同类型的派生类,我必须存储基类的指针,是吗? - jena
1
@jena:是的,你需要在容器中通过指针存储多态类型。然而,接口应该只包含引用,即 T& operator[](size_t i){ return *(foo_ptrs[i]); } - deft_code
@caspin:听起来很合理。因此,如果我想为指针的基础容器提供迭代器访问,我需要编写一个返回引用而不是指针的迭代器,对吗? - jena
@jena:是的,没错。这正是 Boost 指针容器所做的事情。 - Steve Jessop

2
在这种情况下,您可能应该返回一个boost::weak_ptr<>,它可以给您所描述的语义(容器保持所有权,在外部引用被分配后仍然可以删除对象,并且您可以安全地发现对象在外部使用时是否仍然有效)。当然,这需要使用boost::shared_ptr<>,因此可能不适用于您的情况。希望这能帮到您,即使您可能无法使用它。

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