On Nov 28, 3:00 pm, Juha Nieminen <nos...@thanks.invalidwrote:
mike.polya...@gmail.com wrote:
During constructor invocation, a pointer to that function is stored
somewhere inside shared_ptr<A>
That's one thing which I find worrying about shared_ptr. While it's
nice that you can safely create shared_ptrs of incomplete types, the
price for this is that shared_ptr becomes quite bulky. If I'm not
completely mistaken, a shared_ptr object has the size of 3 pointers plus
it allocates dynamically memory for an integral type, which means that
it additionally uses memory required by the integral type plus any
ancillary memory required by a dynamically-allocated object required by
the memory management and possibly memory alignment.
It's typically only two pointers, I think. I can't think of any
reason why there would be a third.
There are two basic philosophies with regards to reference
counted pointers: invasive, and non-invasive. Invasive
reference counted pointers are only a single pointer, require no
extra allocations, and are significantly safer, in that you can
create a new reference counted pointer from a raw pointer at any
time, even if other reference counted pointers already exist.
(Because they are smaller, they are also slightly faster, but
this is rarely an issue.) On the other hand, they are invasive;
the object being pointed to must know about them (typically be
deriving from a common base class---virtually, if the hierarchy
is open). Which means no reference counted pointers to existing
classes, nor to non-class types. For a "standard" pointer,
that's pretty much a killer exclusion.
This means that one single "pointer" could, depending on the
system, require something like 64 bytes or even more. (Compare
this to a system where you have a smart pointer which uses a
reference counter in the object itself, and requires complete
types: Only 1 pointer is needed in the smart pointer object,
and adding the size of the reference counter to it, the total
memory requirement in a typical 32-bit system is 8 bytes.)
That doesn't match up with my measurements. On my 32-bits
systems, alignment considerations mean that the counter itself
ends up requiring 8 bytes, so my invasive reference counted
pointers require a total of n*4+8 bytes for each object (where n
is the number of pointers to that object). I think
boost::shared_ptr requires more, but the one time I implemented
non-invasive reference counting, I used a custom allocator for
the ints, with the result that the pointers required n*8+4
bytes. Not a big difference, unless, of course, you have large
arrays of reference counted pointers.
A much more important consideration is safety. Consider a
simplified example:
T* p = new T ;
Ptr< T p1( p ) ;
Ptr< T p2( p ) ;
With a non-invasive pointer, such as boost::shared_ptr, this
breaks, resulting the memory being freed prematurely. With
invasive pointers, it works.
This can become a major issue if you are, for example, creating an
array of millions of shared_ptrs.
Yes, but is there ever any reason to have a container of
shared_ptr?
Just the shared_ptrs themselves could
easily require more memory than the objects they are point to, if the
objects are small. Since shared_ptr hides this issue very well, a
typical programmer might not be aware of this.
That's even true of the invasive pointers. I'd guess that most
of the time I'm using reference counted pointers, it's for
"agent" classes, with no data members (except for the implicit
vptr).
And better not copy shared_ptrs in a tight inner loop which requires
extreme speed...
I don't think that the difference will normally be that great.
The one case there might be a significant difference is if the
compiler will return (and pass) class types which fit in a
single register in registers. An invasive pointer will
typically fit in a single register, a non-invasive one won't.
But while this optimization has often been discussed, I don't
know of a single compiler which will do it (unless the class
type is a POD, but no reference counted pointer will be a POD).
So it's rather accademic.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34