|
Boost : |
From: Peter Dimov (pdimov_at_[hidden])
Date: 2002-05-08 05:21:19
From: "Gennadiy Rozental" <rogeeff_at_[hidden]>
> I think that shared_ptr named shared not because you "can use different
> deallocators" with the same type (though in some cases it is very
> convenient), but because it model some "Idea" of sharing. The way this
> sharing is achieved is not important - it still should be shared_ptr.
While
> the way how pointer/resource is destroyed is secondary in this sense. Why
> don't you name you semantic: ptr_with_custom_deleter?
Do you argue that you have the right to use the name "shared_ptr" in a way
that is incompatible with the current specification, and that the current
implementation should be renamed to better reflect your ideas of sharing?
That would be great.
> In some cases when we want to emphasize type of sharing in use we may name
> smart pointer as intrusive_ptr or ref_linked_ptr. But what in a name? The
> real issue for me is to understand: do we need "unified" smart_ptr, why,
and
> how it should like.
What does "unified" mean?
shared_ptr's current semantics are carefully crafted to model some of the
raw pointer strengths (the same features can be weaknesses in other
situations, and shared_ptr wouldn't be appropriate here, but I digress.)
In particular:
* shared_ptr works with incomplete classes.
* shared_ptr<T> is a pointer to T and has the same ("unified") interface,
regardless of how T has been allocated (or whether it uses intrusive
counting.)
* shared_ptr supports the usual pointer conversions.
This allows shared_ptr to be used for implementation hiding in situations
where other smart pointers aren't applcable, but raw pointers fare well:
[1]
class file;
shared_ptr<file> fopen(char const * name);
size_t fread(shared_ptr<file> f, void * buffer, size_t n);
[2]
class file
{
struct impl;
shared_ptr<impl> pi_;
public:
explicit file(char const * name);
size_t read(void * buffer, size_t n);
};
[3]
struct interface
{
virtual void method() = 0;
};
shared_ptr<interface> createInstance();
Note that the implementor of createInstance() can change the counting type
or the allocation mechanism without breaking any client code; if
createInstance() is in a shared library, the client doesn't even have to
relink. (This applies to the other examples as well.)
In short, one of the uses of shared_ptr is for implementation hiding; it
insulates the client from the particulars of the implementation. It can be
used with COM-allocated objects in situations where the client does not care
where the object returned is COM.
In contrast, in situations where the client does care about the COM-ness of
the object, one should use a genuine COM smart pointer (which has a
different, non-"unified", interface, understands QueryInterface etc.) There
is no interoperability problem between different COM smart pointers (or
intrusive pointers in general) since you can construct an intrusive pointer
from a raw pointer.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk