关于 boost::shared_ptr 的困惑

发布于 2024-10-06 15:31:46 字数 946 浏览 4 评论 0原文

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

考虑一个有一个雇员的情况。 Employeer在内部将其所有员工维护在向量共享指针<人> >。因此,最佳实践是否规定任何涉及 Person 的接口都应该是一个 shared_ptr 包装的 person ?

例如,全部或仅其中一些可以:

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被删除并使我的引用无效的风险?


有关涉及此问题的示例,请参阅我的新问题

My question revolves around whether or not I must expose my use of the boost::shared_ptr from my interface and whether or not I should expose raw pointers or references from my interface.

Consider the case of a Person who has an Employeer. Employeer internally maintains all of its employees in a vector< shared_ptr< Person > >. Because of this, do best practices dictate that any interface involving Person should be a shared_ptr wrapped person?

For example, are all or only some of these ok:

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

Or for example:

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

If I later want to change the implementation to use johns_very_own_shared_ptr instead of the boost variety, am I trapped in the old implementation?

On the other hand, if I expose raw pointers or references from the interface, do I risk someone deleting the memory out from under the shared_ptr? Or do I risk the shared_ptr being deleted and making my reference invalid?


See my new question for an example involving this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

月牙弯弯 2024-10-13 15:31:46

例如,全部或仅其中一些可以:

这取决于您想要完成的任务。为什么向量保存 shared_ptr 而不是直接按值存储 Person ? (您是否考虑过boost::ptr_vector?)

您还应该考虑也许您真正应该分发的是weak_ptr。

如果我以后想更改实现以使用 johns_very_own_shared_ptr 而不是 boost 品种,我是否会陷入旧的实现中?

差不多,但也不是不可能修复。 (我怀疑在 C++0x 中,自由使用 auto 关键字将使这个问题更容易处理,因为您不必修改调用代码,即使它没有'不要使用 typedef 。)但是,为什么你会想要这样做呢?

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

是的,但这不是你的问题。人们可以从 shared_ptr 中提取原始指针并删除它。但如果您想避免使事情变得不必要的不​​安全,请不要在此处返回原始指针。引用要好得多,因为没有人认为他们应该删除&reference_received_from_api;。 (无论如何,我希望如此^^;;;;)

For example, are all or only some of these ok:

It depends on what you're trying to accomplish. Why does the vector hold shared_ptrs instead of just directly storing Person s by value? (And have you considered boost::ptr_vector?)

You should also consider that maybe what you really ought to hand out is a weak_ptr.

If I later want to change the implementation to use johns_very_own_shared_ptr instead of the boost variety, am I trapped in the old implementation?

Pretty much, but it's not impossible to fix. (I suspect that in C++0x, liberal use of the auto keyword will make this easier to deal with, since you won't have to modify the calling code as much, even if it didn't use typedef s.) But then, why would you ever want to do that?

On the other hand, if I expose raw pointers or references from the interface, do I risk someone deleting the memory out from under the shared_ptr?

Yes, but that's not your problem. People can extract a raw pointer from a shared_ptr and delete it, too. But if you want to avoid making things needlessly unsafe, don't return raw pointers here. References are much better because nobody ever figures they're supposed to delete &reference_received_from_api;. (I hope so, anyway ^^;;;; )

悸初 2024-10-13 15:31:46

我会引入一个 typedef 并使自己免受更改。像这样的事情:

typedef std::shared_ptr<Person> PersonPtr;

PersonPtr Employeer::getPresident() const;

我将这样的 typedef 与前向声明一起放置在(只有一个)标头中。如果我愿意的话,这使得改变变得很容易。

I would introduce a typedef and insulate myself against changes. Something like this:

typedef std::shared_ptr<Person> PersonPtr;

PersonPtr Employeer::getPresident() const;

I place typedefs like this one in a (just one) header together with forward declarations. This makes it easy to change if I would ever want to.

许一世地老天荒 2024-10-13 15:31:46

您不必分发shared_ptr,但如果您分发原始指针,则会面临在对象被销毁后某些原始指针仍然存在的风险。

带来致命的后果。

因此,分发引用通常是可以的(如果客户端代码获取地址,那么这不是你的错,就像客户端代码获取 *shared_ptr 的地址一样),但是原始指针,请首先考虑。

干杯&呵呵,

You don't have to hand out shared_ptr, but if you hand out raw pointers you run the risk of some raw pointer persisting after the object has been destroyed.

With fatal consequences.

So, handing out references generally OK (if client code takes address then that's no more your fault than if client code takes address of *shared_ptr), but raw pointers, think first.

Cheers & hth.,

云裳 2024-10-13 15:31:46

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

要隐藏 boost:shared_ptr 的使用,您可以使用 typedef 隐藏实际类型,并改用这个新类型。

typedef boost::shared_ptr<Person> Person_sptr;

I shouldn't give user raw pointers, when you use shared_ptrs. User could delete it, what will cause double deletion.

To hide usage of boost:shared_ptr you can use typedef to hide actual type, and use this new type instead.

typedef boost::shared_ptr<Person> Person_sptr;
少女净妖师 2024-10-13 15:31:46

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

如果您希望某人在不再是 Employee 后能够访问 Person,那么 shared_ptr 将是合适的。假设您要将Person移动到不同Employervector

The only reason to hand out a shared_ptr here is if the lifetime of the returned object reference is not tied directly to the lifetime of its residence in the vector.

If you want somebody to be able to access the Person after they stop being an Employee, then shared_ptr would be appropriate. Say if you are moving the Person to the vector for a different Employer.

不羁少年 2024-10-13 15:31:46

我从事一个中等规模的项目,该项目链接了多个库。其中一些库有自己的内存管理子系统(APR、MFC),这真的让我很恼火。无论他们的世界观是好还是坏,都与其他人的世界观完全不同,并且需要比其他人更多的代码。

此外,这些库还使用 jemalloc 替换 mallocnew Boehm-Demers-Weiser 垃圾收集器 更加困难( 在 Windows 上这已经够难了)。

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

  1. 分发原始指针(加上指针可以删除的承诺) /code>d 或 Destroy()< /code>函数来调用以解除分配对象)
  2. 接受函数或类似 STL 分配器的参数,以便您可以挂钩用户用于内存管理的任何内容(随意默认为 newstd::allocator
  3. 让你的库用户给你分配的内存缓冲区(like std::vectors)

使用这种库并不一定是令人讨厌的:

// 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());

I work on a moderately sized project that links in several libraries. Some of those libraries have their own memory management subsystems (APR, MFC) and really annoy me. Whether their view of the world is good or bad, it's entirely different from everybody else's and requires a little more code than they otherwise would.

Additionally, those libraries make swapping out malloc or new with jemalloc or the Boehm-Demers-Weiser garbage collector much harder (on Windows it's already hard enough).

I use shared pointers a lot in my own code, but I prefer not to tell others how to manage their memory. Instead, hand out objects whenever possible (letting the library user decide when and how to allocate the memory), and when it's not possible do one of:

  1. hand out raw pointers (plus either a promise that the pointers can be deleted or a Destroy() function to call to deallocate the objects)
  2. accept a function or STL allocator-like argument so you can hook into whatever the user's using for memory management (feel free to default to new and std::allocator)
  3. have your library users hand you allocated memory buffers (like std::vectors)

Using this kind of library doesn't have to be nasty:

// 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());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文