Is this a valid use of intrusive_ptr?

China☆狼群 提交于 2019-12-03 16:18:14
Howard Hinnant

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:

void f(A* a);
void g(std::unique_ptr<A> a);
void h(std::shared_ptr<A> a);

The ownership semantics of f is not clear. If you are the client of f you need to read the documentation to find out if f is going to deallocate a, or ignore ownership issues for a.

The ownership semantics of g is clear. When you call g you pass the ownership of a to g and you are no longer responsible for it. g will either deallocate a or transfer ownership of that resource somewhere else.

The ownership semantics of h is clear. When you call h, you and h become co-owners of a. Last one out turns off the lights.

void q(boost::intrusive_ptr<A> a);

q has the same ownership semantics as h. The main difference is that the following free functions must exist:

intrusive_ptr_add_ref(A*);
intrusive_ptr_release(A*);

If you are the author of f and you call these functions on a, you should document that you do so. Your clients won't necessarily know that you are. And if you are a client of f, you have no way of knowing if f will call these functions unless you read its documentation.

If you are the author of f and you intend on calling the intrusive_ptr_* functions, you can make that explicit in your interface by coding q instead.

But usually there is not a compelling reason to impose on the author of A to write the intrusive_ptr_* functions. And you can get the same ownership semantics as q by writing h instead, without imposing any further requirements on A.

On Memory Overhead

If you create your shared_ptr with:

 shared_ptr<A> p = make_shared(arguments-to-construct-an-A);

then your shared_ptr will have the exact same memory overhead as an intrusive_ptr. The implementation will allocate the A and the refcount in the same memory allocation. Your clients need not know or care that your shared_ptr was constructed so efficiently.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!