关于boost :: shared_ptr的困惑

时间:2010-12-08 16:14:39

标签: c++ pointers reference shared-ptr

我的问题围绕我是否必须从我的界面公开我对boost :: shared_ptr的使用,以及我是否应该从我的界面公开原始指针或引用。

考虑具有 Employeer Person 的情况。 员工在内部维护所有员工vector< shared_ptr< Person > >。因此,最佳实践是否要求任何涉及Person的接口都应该是shared_ptr包装的人?

例如,全部或仅部分是好的:

Person Employeer::getPresidentCopy();
Person& Employeer::getPresidentRef();
Person* Employeer::getPresidentRawPtr();
shared_ptr<Person> Employeer::getPresidentSharedPtr();

或者例如:

void Employeer::hireByCopy(Person p);
void Employeer::hireByRef(Person& p);
void Employeer::hireByRawPtr(Person* p);
void Employeer::hireBySharedPtr(shared_ptr<Person> p);

如果我以后想要更改实现以使用johns_very_own_shared_ptr而不是boost类型,我是否被困在旧实现中?

另一方面,如果我从接口公开原始指针或引用,我是否冒险从shared_ptr下删除内存?或者我是否冒险删除shared_ptr并使我的引用无效?


请参阅我的new question以获取涉及此问题的示例。

6 个答案:

答案 0 :(得分:3)

我会介绍一个typedef并让自己与变化保持隔离。像这样:

typedef std::shared_ptr<Person> PersonPtr;

PersonPtr Employeer::getPresident() const;

我将这样的typedef放在一个(只有一个)标题中以及前向声明。如果我愿意,这可以很容易地改变。

答案 1 :(得分:3)

  

例如,全部或仅部分是好的:

这取决于你想要完成的事情。为什么向量保持shared_ptr而不是仅按值直接存储Person? (你考虑过boost::ptr_vector吗?)

您还应该考虑一下,您真正​​应该分发的是weak_ptr

  

如果我以后想要更改实现以使用johns_very_own_shared_ptr而不是boost类型,我是否被困在旧实现中?

差不多,但修复并非不可能。 (我怀疑在C ++ 0x中,自由使用auto关键字会使这更容易处理,因为你不必修改调用代码,即使它没有使用{ {1}} s。)但是,那么,为什么你会想要这样做呢?

  

另一方面,如果我从界面公开原始指针或引用,是否有人冒险从shared_ptr下删除内存?

是的,但那不是你的问题。人们也可以从typedefshared_ptr中提取原始指针。但是如果你想避免让事情变得不安全,不要在这里返回原始指针。引用要好得多,因为没有人认为他们应该 delete。 (我希望如此,无论如何^^ ;;;;)

答案 2 :(得分:2)

你不必分发shared_ptr,但是如果你分发原始指针,你就会冒一些原始指针在对象被销毁后持续存在的风险。

致命的后果。

所以,一般都可以分发参考文献(如果客户端代码需要地址,那么这不是你的错,而不是客户端代码获取* shared_ptr的地址),但原始指针首先考虑。

干杯&amp;第h。,

答案 3 :(得分:2)

当您使用shared_ptr时,我不应该给用户原始指针。用户可以删除它,什么会导致双重删除。

要隐藏boost:shared_ptr的使用情况,您可以使用typedef隐藏实际类型,并使用此新类型。

typedef boost::shared_ptr<Person> Person_sptr;

答案 4 :(得分:1)

在此处分发shared_ptr的唯一原因是返回的对象引用的生命周期与向量中其驻留的生命周期没有直接关系。

如果您希望某人在Person停止后能够访问Employee,则shared_ptr将是合适的。假设您要将Person移至vector以获取其他Employer

答案 5 :(得分:0)

我在一个中等规模的项目上工作,该项目链接在几个库中。其中一些库有自己的内存管理子系统(APR,MFC),真的很烦我。无论他们对世界的看法是好还是坏,都与其他人完全不同,并且需要的代码比其他人要多得多。

此外,这些图书馆会将mallocnew换成jemallocBoehm-Demers-Weiser garbage collector更难(on Windows it's already hard enough)。

我在自己的代码中经常使用共享指针,但我不想告诉别人如何管理他们的内存。相反,尽可能分发对象(让库用户决定何时以及如何分配内存),以及什么时候不可能执行以下操作之一:

  1. 分发原始指针(加上指针可以是delete d或Destroy()函数来调用以取消分配对象)
  2. 接受一个函数或类似STL分配器的参数,以便您可以挂钩用户进行内存管理的任何内容(可以默认为newstd::allocator
  3. 让您的图书馆用户为您分配内存缓冲区(like std::vectors
  4. 使用这种库不一定要讨厌:

    // situation (1) from above
    std::shared_ptr<Foo> foo(Library_factory::get_Foo(), Library_factory::deallocate);
    
    // situation (2) above (declaration on next line is in a header file)
    template<typename allocator=std::allocator<Foo> > Foo* library_function_call();
    boost::shared_ptr<Foo> foo = library_function_call();
    
    // situation (3) above, need to fill a buffer of ten objects
    std::vector<Foo> foo_buffer(10);
    fill_buffer(&foo_buffer[0], foo_buffer.size());