By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,156 Members | 1,028 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,156 IT Pros & Developers. It's quick & easy.

Smart pointers and this

P: n/a
I'm using reference counted smart pointers in a small project and it's
a breeze, but I'm running into a problem which I don't know how to
approach.

Consider something like this:

class A {
public:
A() {}
void setObserver(counted_ptr<Bobserver) { _observer =
observer; }

private:
counted_ptr<B_observer;
};

class B {
public:
B() {
_a = counted_ptr<A>(new A);
_a->setObserver(counted_ptr<B>(this));
}

private:
counted_ptr<A_a;
};
>From what I can see, the problem is creating a smart pointer with an
already existing raw pointer. In this case, the problem is that when
A's destructor is called (while B is being destroyed), it will destroy
_observer, which having a ref count of 1, will delete the pointed
object (B), which is not a good thing.

The easiest alternative I thought for this case is using a reference
instead, but I'd like to know if there's some way to fix this problem
(having an extra reference to avoid deletion somehow, etc)

Thanks!

Sep 18 '07 #1
Share this Question
Share on Google+
7 Replies


P: n/a
si*********@gmail.com wrote:
I'm using reference counted smart pointers in a small project and it's
a breeze, but I'm running into a problem which I don't know how to
approach.

Consider something like this:

class A {
public:
A() {}
void setObserver(counted_ptr<Bobserver) { _observer =
observer; }

private:
counted_ptr<B_observer;
};

class B {
public:
B() {
_a = counted_ptr<A>(new A);
_a->setObserver(counted_ptr<B>(this));
}

private:
counted_ptr<A_a;
};
>>From what I can see, the problem is creating a smart pointer with an
already existing raw pointer. In this case, the problem is that when
A's destructor is called (while B is being destroyed), it will destroy
_observer, which having a ref count of 1, will delete the pointed
object (B), which is not a good thing.

The easiest alternative I thought for this case is using a reference
instead, but I'd like to know if there's some way to fix this problem
(having an extra reference to avoid deletion somehow, etc)
Your best bet is to use boost::shared_ptr and boost::weak_ptr. See
http://www.boost.org/libs/smart_ptr/smart_ptr.htm for more information.

Joe Gottman
Sep 18 '07 #2

P: n/a
si*********@gmail.com wrote:
I'm using reference counted smart pointers in a small project and it's
a breeze, but I'm running into a problem which I don't know how to
approach.

Consider something like this:

class A {
public:
A() {}
void setObserver(counted_ptr<Bobserver) { _observer =
observer; }

private:
counted_ptr<B_observer;
};

class B {
public:
B() {
_a = counted_ptr<A>(new A);
_a->setObserver(counted_ptr<B>(this));
}

private:
counted_ptr<A_a;
};
>>From what I can see, the problem is creating a smart pointer with an
already existing raw pointer. In this case, the problem is that when
A's destructor is called (while B is being destroyed), it will destroy
_observer, which having a ref count of 1, will delete the pointed
object (B), which is not a good thing.
A & B objects would never get deleted. You need to decide who owns who.
You then need a smart pointer type that does not assume ownership
(usually referred to as a weak pointer). Austria C++ uses Ptr and
PtrView (Ptr for ownership and PtrView as a weak pointer). Boost I
think uses shared_ptr and weak_ptr.
>
The easiest alternative I thought for this case is using a reference
instead, but I'd like to know if there's some way to fix this problem
(having an extra reference to avoid deletion somehow, etc)
This is a design issue. Cyclic graphs of smart pointers must be avoided
in your design, otherwise you will have issues.
Sep 18 '07 #3

P: n/a
Your best bet is to use boost::shared_ptr and boost::weak_ptr. Seehttp://www.boost.org/libs/smart_ptr/smart_ptr.htmfor more information.

Aha! seems that I'm not the first one having this problem.. Many
thanks, this looks interesting, although the FAQ at the end of this
page http://www.boost.org/libs/smart_ptr/weak_ptr.htm seems to say
that I can't use this as intended in the example snippet (inside a
ctor). Anyway I'll search for further info about these weak pointers.
Thanks for the hint.

Sep 18 '07 #4

P: n/a
On Sep 18, 4:53 pm, sip.addr...@gmail.com wrote:
Your best bet is to use boost::shared_ptr and boost::weak_ptr. Seehttp://www.boost.org/libs/smart_ptr/smart_ptr.htmformore information.

Aha! seems that I'm not the first one having this problem.. Many
thanks, this looks interesting, although the FAQ at the end of this
pagehttp://www.boost.org/libs/smart_ptr/weak_ptr.htmseems to say
that I can't use this as intended in the example snippet (inside a
ctor). Anyway I'll search for further info about these weak pointers.
Thanks for the hint.
boost:enable_shared_from_this

Sep 19 '07 #5

P: n/a
On Sep 19, 1:53 am, sip.addr...@gmail.com wrote:
Your best bet is to use boost::shared_ptr and boost::weak_ptr. Seehttp://www.boost.org/libs/smart_ptr/smart_ptr.htmformore information.

Aha! seems that I'm not the first one having this problem.. Many
thanks, this looks interesting, although the FAQ at the end of this
pagehttp://www.boost.org/libs/smart_ptr/weak_ptr.htmseems to say
that I can't use this as intended in the example snippet (inside a
ctor). Anyway I'll search for further info about these weak pointers.
Thanks for the hint.
I would also like to thank Gianni Mariani and Tim H for their helpful
replies. Unfortunately it seems that google news don't display them
for some reason (I only get to see 3 of the 5 messages in the thread!)

Regarding Gianni's last point:
This is a design issue. Cyclic graphs of smart pointers must be avoided
in your design, otherwise you will have issues.
The only thing I'm expecting to use is a simple observer facility. A
parent class creates a child class, and needs to get notified of some
events generated by this child class. So after instantiating the
child, I register the parent to listen for events. I think this is the
easiest way to achieve this. Are there better alternatives?

Thank you.

Sep 22 '07 #6

P: n/a
On Sep 19, 1:05 am, sip.addr...@gmail.com wrote:
I'm using reference counted smart pointers in a small project and it's
a breeze, but I'm running into a problem which I don't know how to
approach.
Consider something like this:
class A {
public:
A() {}
void setObserver(counted_ptr<Bobserver) { _observer =
observer; }
private:
counted_ptr<B_observer;
};
class B {
public:
B() {
_a = counted_ptr<A>(new A);
_a->setObserver(counted_ptr<B>(this));
}
private:
counted_ptr<A_a;
};
From what I can see, the problem is creating a smart pointer with an
already existing raw pointer. In this case, the problem is that when
A's destructor is called (while B is being destroyed), it will destroy
_observer, which having a ref count of 1, will delete the pointed
object (B), which is not a good thing.
Presumably, your counted_ptr is similar to boost::shared_ptr.
If so, you're misusing it. It represents *shared* ownership
(which is actually pretty rare), and the observer pattern
doesn't involve ownership. It's pure navigation, which means
that you should probably be using raw pointers (although there
are special cases when some other type of smart pointer might be
appropriate).
The easiest alternative I thought for this case is using a
reference instead, but I'd like to know if there's some way to
fix this problem (having an extra reference to avoid deletion
somehow, etc)
Just use a raw pointer. In general, when pointers are used for
navigation, rather than for ownership, raw pointers are the most
appropriate solution.

--
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

Sep 23 '07 #7

P: n/a

sip.addr...@gmail.com wrote:

Regarding Gianni's last point:
This is a design issue. Cyclic graphs of smart pointers must be avoided
in your design, otherwise you will have issues.

The only thing I'm expecting to use is a simple observer facility. A
parent class creates a child class, and needs to get notified of some
events generated by this child class. So after instantiating the
child, I register the parent to listen for events. I think this is the
easiest way to achieve this. Are there better alternatives?
While it can be noted that cyclic graphs must be avoided, weak
pointers can break these cycles. I've had problems very
recently where I attempted to write a generic
subscriber/observer which, if you inherited from it automatically
subscribed during construction, and unsubscribed at destruction.

The problem was that one could not use normal pointers, as
the subject (publisher) then had to notify its observers when
it got deleted so the observers who kept a reference did not call
unsubscribe on the invalid reference. To take it further, one part
of the application was decoupled from another by observing the
other and visa versa, therefore one had not choice but either
explicitly unsubscribe, or face UB. The solution was simply to
use weak pointers conservatively. One could probably have used
policies, making weak_ptr the default policy, and allowing the
user to define a reference or pointer policy if he chooses.

Regards,

Werner

Sep 23 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.