Newbie question about 'boost::shared_ptr'

F

for.fun

Hi everybody,


I just read the 'shared_ptr' doc from the Boost site (at
http://www.boost.org/libs/smart_ptr/shared_ptr.htm)


There is a point I do not understand !


1/ Suppose you want to create a 'shared_ptr' on the 'MyClass' object

2/ My instanciation code could like this :

shared_ptr<MyClass> spMyClass(new MyClass);


3/ You can note that my Smart Pointer constructor argument is of
'MyClass *' type.

4/ In the Boost documentation, you can find this :

shared_ptr<T> p(new Y);


... which suppose that T and Y can be of different type.


The problem is I can not understand how T can be different from Y.
As the definition says, the Smart Pointer type 'shared_ptr<T>' is a T
Smart Pointer (a smart T *) so the Smart Pointer argument should always
be of type 'T *'


=> Is it possible to have different types for T and Y ? Why and how is
it possible ?


Thanks in advance for your reply.
 
Z

Zara

Hi everybody,


I just read the 'shared_ptr' doc from the Boost site (at
http://www.boost.org/libs/smart_ptr/shared_ptr.htm)


There is a point I do not understand !


1/ Suppose you want to create a 'shared_ptr' on the 'MyClass' object

2/ My instanciation code could like this :

shared_ptr<MyClass> spMyClass(new MyClass);


3/ You can note that my Smart Pointer constructor argument is of
'MyClass *' type.

4/ In the Boost documentation, you can find this :

shared_ptr<T> p(new Y);


... which suppose that T and Y can be of different type.


The problem is I can not understand how T can be different from Y.
As the definition says, the Smart Pointer type 'shared_ptr<T>' is a T
Smart Pointer (a smart T *) so the Smart Pointer argument should always
be of type 'T *'


=> Is it possible to have different types for T and Y ? Why and how is
it possible ?


Thanks in advance for your reply.


Suppose:

class Y:public T {/*.....*/};

Now you have a type Y different from T, but a pointer to Y may be used
where a pointer to T is, such as in sared_ptr.

To Make it work right, T should have a virtual destructor!
 
K

Kristo

In the Boost documentation, you can find this :

shared_ptr<T> p(new Y);


... which suppose that T and Y can be of different type.


The problem is I can not understand how T can be different from Y.
As the definition says, the Smart Pointer type 'shared_ptr<T>' is a T
Smart Pointer (a smart T *) so the Smart Pointer argument should always
be of type 'T *'


=> Is it possible to have different types for T and Y ? Why and how is
it possible ?

It's possible if T is a parent (or grandparent, etc.) class of Y. It
would then be legal to assign a Y* to a T*.

Kristo
 
P

Pete Becker

Zara said:
Suppose:

class Y:public T {/*.....*/};

Now you have a type Y different from T, but a pointer to Y may be used
where a pointer to T is, such as in sared_ptr.

To Make it work right, T should have a virtual destructor!

T does not have to have a virtual destructor. std::tr1::shared_ptr keeps
track of the original type, and when it destroys the resource it deletes
it through the pointer that was passed to the constructor.
 
R

Razzer

Pete said:
T does not have to have a virtual destructor. std::tr1::shared_ptr keeps
track of the original type, and when it destroys the resource it deletes
it through the pointer that was passed to the constructor.

So let's assume something like this:

//Necessary header files included

class X { public: ~X() { } };
class Y : public X { public: ~Y() { } };

int main( void )
{
std::tr1::shared_ptr<X> x(new Y());
}

Would shared_ptr call ~Y in this instance as well?
 
P

Pete Becker

Razzer said:
So let's assume something like this:

//Necessary header files included

class X { public: ~X() { } };
class Y : public X { public: ~Y() { } };

int main( void )
{
std::tr1::shared_ptr<X> x(new Y());
}

Would shared_ptr call ~Y in this instance as well?

Yes. And it would do the same for

shared_ptr<void>(new Y);

That's why it's called a smart pointer. <g>
 
R

Razzer

Pete said:
Yes. And it would do the same for

shared_ptr<void>(new Y);

That's why it's called a smart pointer. <g>

What about:

X *p = new Y;
shared_ptr<X>(p);

?

It seems, to me, that the template scheme used would have met its match
in this instance.
 
P

Pete Becker

Razzer said:
What about:

X *p = new Y;
shared_ptr<X>(p);

?

It seems, to me, that the template scheme used would have met its match
in this instance.

shared_ptr only knows what it's privy to. You can subvert it if you try.
This kind of coding, though, is bad news even if X has a virtual
destructor. If you write code that traffics in raw pointers and
shared_ptr objects that try to manage the same resource you're going to
get burned.
 
J

Jack Saalweachter

Pete said:
shared_ptr only knows what it's privy to. You can subvert it if you try.
This kind of coding, though, is bad news even if X has a virtual
destructor. If you write code that traffics in raw pointers and
shared_ptr objects that try to manage the same resource you're going to
get burned.
You're _always_ better off writing virtual destructors when you know
you're going to be using inheritance. shared_ptr just happens to allow
you to get away with /not/ doing the right thing.

In any case, this is a Good Example of why some famous paradigm or
another says, Thou Shalt Not Allocate Memory Outside Of The Constructor
Call For A Smart Pointer. Always say "shared_ptr<X>(new Y);", never "X
*x = new Y;" or even "Y *y = new Y;".

I /think/ there is also a second reason. If I recall correctly, it goes
something like this. Suppose you write:

Y *y = new Y;
shared_ptr<X> x(y);

Now, suppose your constructor fails. It has to allocate memory of its
own, after all, and this allocation could fail, and then an exception is
thrown, and you run the risk of y leaking. You'd have to get all ugly
and say something like:

Y *y = new Y;
try {
shared_ptr<X> x(y);
} catch (...) {
delete y;
}

Long story short, you have to start bending over backwards and manually
managing your memory ... which is exactly what smart points are supposed
to save you from. If, however, you say:

shared_ptr<X> x(new Y);

something completely different happens. The Blessed Standard, I do
believe, dictates that in this case, should x throw an exception during
construction, the memory we allocated will automatically disappear, like
magic. No memory leak, no manual memory management.


So, Thou Shalt Not Allocate Memory Outside Of The Constructor Call For A
Small Pointer, Lest Thee Lose Type Information And Incur Memory Leaks.
 
P

Pete Becker

Jack said:
You're _always_ better off writing virtual destructors when you know
you're going to be using inheritance. shared_ptr just happens to allow
you to get away with /not/ doing the right thing.

No, shared_ptr is deliberately designed to handle this case correctly.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top