关于 boost::shared_ptr 的困惑
我的问题围绕着是否必须从接口公开 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这取决于您想要完成的任务。为什么向量保存
shared_ptr
而不是直接按值存储Person
? (您是否考虑过boost::ptr_vector?)您还应该考虑也许您真正应该分发的是weak_ptr。
差不多,但也不是不可能修复。 (我怀疑在 C++0x 中,自由使用
auto
关键字将使这个问题更容易处理,因为您不必修改调用代码,即使它没有'不要使用typedef
。)但是,为什么你会想要这样做呢?是的,但这不是你的问题。人们可以从
shared_ptr
中提取原始指针并删除
它。但如果您想避免使事情变得不必要的不安全,请不要在此处返回原始指针。引用要好得多,因为没有人认为他们应该删除&reference_received_from_api;
。 (无论如何,我希望如此^^;;;;)It depends on what you're trying to accomplish. Why does the vector hold
shared_ptr
s instead of just directly storingPerson
s by value? (And have you consideredboost::ptr_vector
?)You should also consider that maybe what you really ought to hand out is a
weak_ptr
.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 usetypedef
s.) But then, why would you ever want to do that?Yes, but that's not your problem. People can extract a raw pointer from a
shared_ptr
anddelete
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 todelete &reference_received_from_api;
. (I hope so, anyway ^^;;;; )我会引入一个
typedef
并使自己免受更改。像这样的事情:我将这样的 typedef 与前向声明一起放置在(只有一个)标头中。如果我愿意的话,这使得改变变得很容易。
I would introduce a
typedef
and insulate myself against changes. Something like this: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.
您不必分发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.,
当您使用
shared_ptr
时,我不应该给用户原始指针。用户可以删除它,这会导致重复删除。要隐藏
boost:shared_ptr
的使用,您可以使用typedef
隐藏实际类型,并改用这个新类型。I shouldn't give user raw pointers, when you use
shared_ptr
s. User could delete it, what will cause double deletion.To hide usage of
boost:shared_ptr
you can usetypedef
to hide actual type, and use this new type instead.此处分发
shared_ptr
的唯一原因是返回的对象引用的生命周期是否与其在向量中驻留的生命周期直接相关。如果您希望某人在不再是
Employee
后能够访问Person
,那么shared_ptr
将是合适的。假设您要将Person
移动到不同Employer
的vector
。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 anEmployee
, thenshared_ptr
would be appropriate. Say if you are moving thePerson
to thevector
for a differentEmployer
.我从事一个中等规模的项目,该项目链接了多个库。其中一些库有自己的内存管理子系统(APR、MFC),这真的让我很恼火。无论他们的世界观是好还是坏,都与其他人的世界观完全不同,并且需要比其他人更多的代码。
此外,这些库还使用 jemalloc 替换
malloc
或new
或 Boehm-Demers-Weiser 垃圾收集器 更加困难( 在 Windows 上这已经够难了)。我在自己的代码中经常使用共享指针,但我不想告诉其他人如何管理他们的内存。相反,只要有可能,就分发对象(让库用户决定何时以及如何分配内存),而当不可能时,执行以下操作之一:
Destroy()< /code>
函数来调用以解除分配对象)
new
和std::allocator
)std::vector
s)使用这种库并不一定是令人讨厌的:
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
ornew
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:
delete
d or aDestroy()
function to call to deallocate the objects)new
andstd::allocator
)std::vector
s)Using this kind of library doesn't have to be nasty: