在我的代码中,涉及intrusive_ptrs时,我遵循两个规则:
许多Internet评论员已经写道,与第三方代码相比,shared_ptr应该比intrusive_ptr更可取。但是,intrusive_ptr避免了智能指针的传递,因为您可以从原始指针创建intrusive_ptr,就像在函数生命周期之外需要该对象时一样。
我只是担心我会丢失某些东西,因为我读到的东西都没有涉及到intrusive_ptrs,而且大多数人似乎更喜欢shared_ptrs,即使它们在使用enable_shared_from_this和继承时会带来内存开销以及问题。
最佳答案
只有在绝对必要的情况下,才应该在具有所有权语义的公共(public)API中传递原始指针。例如。与您不能更改其接口(interface)的代码接口(interface)。
在私有(private)API中传递原始指针,例如单个类(class)内的成员没有问题。
请考虑以下三个功能:
void f(A* a);
void g(std::unique_ptr<A> a);
void h(std::shared_ptr<A> a);
f
的所有权语义尚不清楚。如果您是f
的客户,则需要阅读文档以了解f
是要取消分配a
还是忽略a
的所有权问题。g
的所有权语义很明确。当您调用g
时,会将a
的所有权传递给g
,而您不再对此负责。 g
将取消分配a
或将该资源的所有权转移到其他地方。h
的所有权语义很明确。调用h
时,您和h
成为a
的共同所有者。最后一个熄灭灯。void q(boost::intrusive_ptr<A> a);
q
具有与h
相同的所有权语义。主要区别在于必须存在以下自由函数:intrusive_ptr_add_ref(A*);
intrusive_ptr_release(A*);
如果您是
f
的作者,并且在a
上调用了这些函数,则应记录您这样做的情况。您的客户不一定知道您是。而且,如果您是f
的客户,则除非您阅读f
的文档,否则您将无法知道f
是否将调用这些函数。如果您是
intrusive_ptr_*
的作者,并且打算调用q
函数,则可以通过对A
进行编码来在界面中将其明确显示。但是通常没有令人信服的理由强加给
intrusive_ptr_*
的作者来编写q
函数。而且,您可以通过编写h
来获得与ojit_code相同的所有权语义,而无需在A
上对施加任何进一步的要求。内存开销
如果您使用以下方法创建
shared_ptr
: shared_ptr<A> p = make_shared(arguments-to-construct-an-A);
那么您的
shared_ptr
将具有与intrusive_ptr
完全相同的内存开销。该实现将在同一内存分配中分配A和refcount。您的客户不需要知道或关心您的shared_ptr
如此高效地构造。