这是 intrusive_ptr 的有效使用吗?
在我的代码中,当涉及到 intrusive_ptr 时,我遵循两条规则:
- 按值传递原始指针意味着保证原始指针在该函数的生命周期内有效。
- 如果要在函数的生命周期之外存储和使用原始指针,则应将其存储在 intrusive_ptr 中。
许多互联网评论者写道,除非使用第三方代码,否则shared_ptr应该优于intrusive_ptr。但是,intrusive_ptr 避免了传递智能指针,因为您可以从原始指针创建 intrusive_ptr,就像在函数的生命周期之外需要该对象时一样。
我只是担心我遗漏了一些东西,因为我读过的任何内容都没有说明有关 intrusive_ptrs 的这一点,而且大多数人似乎更喜欢共享指针,即使它们会带来内存开销,并且在使用 enable_shared_from_this 和继承时也会出现问题。
Within my code I follow two rules when it comes to intrusive_ptrs:
- Passing a raw pointer by value implies that the raw pointer is guaranteed to be valid during the lifetime of that function.
- If the raw pointer is to be stored and used beyond the lifetime of the function, it should be stored in an intrusive_ptr.
Many Internet commenters have written that shared_ptr should be preferred over intrusive_ptr except when working with third party code. However, intrusive_ptr obviates passing around smart pointers since you can create an intrusive_ptr from a raw pointer, as when the object is needed beyond the lifetime of the function.
I'm just concerned that I'm missing something because nothing that I've read has made this point about intrusive_ptrs, and that most people seem to prefer shared_ptrs even though they introduce memory overhead and also problems when using enable_shared_from_this and inheritance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在具有所有权语义的公共 API 中传递原始指针应该很少进行,并且仅在绝对必要时才进行。例如,与您无法更改其接口的代码进行交互。
在私有 API 中(例如在单个类的成员中)传递原始指针是没有问题的。
考虑这三个函数:
f
的所有权语义不清楚。如果您是f
的客户,您需要阅读文档以了解f
是否要释放a
,或者忽略所有权问题一个
。g
的所有权语义很清楚。当您调用g
时,您将a
的所有权传递给g
,并且您不再对此负责。g
将释放a
或将该资源的所有权转移到其他地方。h
的所有权语义很清楚。当您调用h
时,您和h
就成为a
的共同所有者。最后一个出去的人关灯。q
与h
具有相同的所有权语义。主要区别在于,必须存在以下自由函数:如果您是
f
的作者,并且在a
上调用这些函数,则应该记录您这样做的情况。您的客户不一定知道您是这样。如果您是f
的客户,除非您阅读其文档,否则您无法知道f
是否会调用这些函数。如果您是
f
的作者,并且打算调用intrusive_ptr_*
函数,则可以通过编码q
来在界面中明确这一点。但通常没有令人信服的理由迫使
A
的作者编写intrusive_ptr_*
函数。您可以通过编写h
来获得与q
相同的所有权语义,而无需对A
强加任何进一步的要求。关于内存开销
如果您使用以下方式创建
shared_ptr
:那么您的
shared_ptr
将具有与intrusive_ptr
完全相同的内存开销>。该实现将在同一内存分配中分配 A 和引用计数。您的客户不需要知道或关心您的shared_ptr
的构建如此高效。Passing a raw pointer around in a public API that has ownership semantics should be done only rarely, and only when absolutely necessary. E.g. interfacing with code whose interface you can not change.
Passing around a raw pointer in a private API, e.g. within the members of a single class is no problem.
Consider these three functions:
The ownership semantics of
f
is not clear. If you are the client off
you need to read the documentation to find out iff
is going to deallocatea
, or ignore ownership issues fora
.The ownership semantics of
g
is clear. When you callg
you pass the ownership ofa
tog
and you are no longer responsible for it.g
will either deallocatea
or transfer ownership of that resource somewhere else.The ownership semantics of
h
is clear. When you callh
, you andh
become co-owners ofa
. Last one out turns off the lights.q
has the same ownership semantics ash
. The main difference is that the following free functions must exist:If you are the author of
f
and you call these functions ona
, you should document that you do so. Your clients won't necessarily know that you are. And if you are a client off
, you have no way of knowing iff
will call these functions unless you read its documentation.If you are the author of
f
and you intend on calling theintrusive_ptr_*
functions, you can make that explicit in your interface by codingq
instead.But usually there is not a compelling reason to impose on the author of
A
to write theintrusive_ptr_*
functions. And you can get the same ownership semantics asq
by writingh
instead, without imposing any further requirements onA
.On Memory Overhead
If you create your
shared_ptr
with:then your
shared_ptr
will have the exact same memory overhead as anintrusive_ptr
. The implementation will allocate the A and the refcount in the same memory allocation. Your clients need not know or care that yourshared_ptr
was constructed so efficiently.intrusive_ptr 确实有其他代价:您必须使用内存管理信息来混淆您的实际设计,您使事情变得比所需的更复杂,项目的贡献者不会熟悉您的推理(甚至 intrusive_ptr)并且您需要更多文档。
另外:您是否曾经对复制智能指针的开销实际上影响您的应用程序进行过基准测试?我宁愿先使用简单版本,并且仅在真正必要时才引入 intrusive_ptr 。
intrusive_ptr does come with other prices: you have to clutter your actual design with memory management information, you are making things more complicated than required, contributors to your project wont be familiar with your reasoning (and even intrusive_ptr) and you need more documentation.
Also: have you ever benchmarked that the overhead of copying smart pointers is actually affecting your application? I'd rather go with the simple version first and would introduce intrusive_ptr only when really necessary.