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.