这是intrusive_ptr的有效用法吗?

Bry*_*man 4 c++ boost smart-pointers

在我的代码中,我在涉及intrusive_ptrs时遵循两条规则:

  • 按值传递原始指针意味着原始指针在该函数的生命周期内保证有效.
  • 如果要在函数的生命周期之外存储和使用原始指针,则应将其存储在intrusive_ptr中.

许多互联网评论者写道,除了使用第三方代码外,shared_ptr应优先于intrusive_ptr.但是,intrusive_ptr避免了传递智能指针,因为您可以从原始指针创建intrusive_ptr,就像在函数的生命周期之外需要对象一样.

我只是担心我遗漏了一些东西,因为我读过的任何东西都没有说明关于intrusive_ptrs的观点,并且大多数人似乎更喜欢shared_ptrs,即使它们引入内存开销以及使用enable_shared_from_this和继承时的问题.

How*_*ant 9

在具有所有权语义的公共API中传递原始指针应该很少进行,并且仅在绝对必要时才进行.例如,与无法更改其接口的代码连接.

在私有API中传递原始指针,例如在单个类的成员中传递是没有问题的.

考虑这三个功能:

void f(A* a);
void g(std::unique_ptr<A> a);
void h(std::shared_ptr<A> a);
Run Code Online (Sandbox Code Playgroud)

所有权语义f尚不清楚.如果您是客户,则f需要阅读文档以了解是否f要解除分配a,或忽略所有权问题a.

所有权语义g很明确.当您致电时,g您将所有权转让ag您,并且您不再对此负责. g将在a其他地方解除分配或转移该资源的所有权.

所有权语义h很明确.当你打电话时h,你和你h成为了共同拥有者a.最后一个关灯.

void q(boost::intrusive_ptr<A> a);
Run Code Online (Sandbox Code Playgroud)

q具有相同的所有权语义h.主要区别在于必须存在以下自由函数:

intrusive_ptr_add_ref(A*);
intrusive_ptr_release(A*);
Run Code Online (Sandbox Code Playgroud)

如果您是作者,f并且您打开这些函数a,则应记录您这样做.您的客户不一定知道您的身份.如果您是客户f,f除非您阅读其文档,否则您无法知道是否会调用这些函数.

如果您是作者f并且打算调用这些intrusive_ptr_*函数,则可以通过编码在您的界面中明确表示q.

但通常没有令人信服的理由强加A写作者的作者intrusive_ptr_*.并且您可以q通过编写获得相同的所有权语义,h而无需对其进行任何进一步的要求A.

关于记忆开销

如果你创建你shared_ptr的:

 shared_ptr<A> p = make_shared(arguments-to-construct-an-A);
Run Code Online (Sandbox Code Playgroud)

然后你的shared_ptr内存开销就像一个完全相同的内存intrusive_ptr.实现将在同一内存分配中分配A和refcount.您的客户无需了解或关心您的shared_ptr构建如此有效.

  • 如果使用`make_shared`创建`shared_ptr`,你会写'shared_ptr`将具有*完全相同的内存开销*作为`intrusive_ptr`.您是否可能要写相同数量的分配*?AFAIK,一个`shared_ptr`实例占用相应`intrusive_ptr`实例的空间的至少两倍,并且`shared_pointer`的相关参考计数器也至少是`intrusive_ptr`的计数器的两倍(因为`shared_ptr) `还必须计算链接的'weak_ptr`实例). (3认同)