Is it bad to use references in these cases?

S

sip.address

Hi everyone,

A while ago I asked for help about using smart pointers (ie.
shared_ptr) in cyclic situations. Weak ptrs popped out and I gave it a
try, but to be honest, I don't feel very comfortable with them.

Would using references be a bad choice? The more I think about it the
more I realize it shouldn't be any problem with them, so could it be a
good use case?

As a refresher, this would be one situation where I'm planning to use
it:

class provider {
public:
provider(observer& obs) : obs_(obs) {}

private:
observer& obs_;
};

class creator : public observer
{
public:
creator() : provider_(new provider(*this))
{}

private:
shared_ptr<provider> provider_;
};

Where observer would be an abstract class with some defined pure
virtual functions..

Could someone tell me what advantage would have using weak pointers
instead of plain references?
I don't see any danger here, as the provider class will be destroyed
while the creator is being destroyed. So the provider can be sure that
creator will always exist. Any pitfall here?

Only thing that I don't like too much is using this in the ctor, but I
think this is safe to do in this particular case..

And besides (I'm deviating the discussion a bit here), using weaker
pointers wouldn't help too much in the hypothetic case that the (weak)
pointer became invalid, as we'd need to constantly check for nullity
which is quite a pain. I thought about using the null pattern in some
situations, but if I stick to references I wouldn't mind really..

I'd appreciate any comment from you experts.

Regards.
 
J

James Kanze

A while ago I asked for help about using smart pointers (ie.
shared_ptr) in cyclic situations. Weak ptrs popped out and I
gave it a try, but to be honest, I don't feel very comfortable
with them.
Understandably.

Would using references be a bad choice? The more I think about
it the more I realize it shouldn't be any problem with them,
so could it be a good use case?

If the value can never be null, and it need never change,
references are a possibility. Generally, however, for
navigation, raw pointers are still the best solution.
As a refresher, this would be one situation where I'm planning
to use it:
class provider {
public:
provider(observer& obs) : obs_(obs) {}
private:
observer& obs_;
};
class creator : public observer
{
public:
creator() : provider_(new provider(*this))
{}

private:
shared_ptr<provider> provider_;
};
Where observer would be an abstract class with some defined
pure virtual functions..
Could someone tell me what advantage would have using weak
pointers instead of plain references?

This looks like navigation: what's wrong with a raw pointer.
References as class members have two "disadvantages": they can't
be null, and they can't be changed (which makes implementing
assignment very difficult). If the fact that the "pointer"
can't be null is a pre-condition/invariant, and the class
doesn't support assignment, references are fine. Otherwise, raw
pointers may be the most appropriate solution.
I don't see any danger here, as the provider class will be
destroyed while the creator is being destroyed. So the
provider can be sure that creator will always exist. Any
pitfall here?
Only thing that I don't like too much is using this in the
ctor, but I think this is safe to do in this particular case..
And besides (I'm deviating the discussion a bit here), using
weaker pointers wouldn't help too much in the hypothetic case
that the (weak) pointer became invalid, as we'd need to
constantly check for nullity which is quite a pain. I thought
about using the null pattern in some situations, but if I
stick to references I wouldn't mind really..
I'd appreciate any comment from you experts.

If the pointer is only used for navigation, then a raw pointer
is all you need.
 
J

Joe Greer

Would using references be a bad choice? The more I think about it the
more I realize it shouldn't be any problem with them, so could it be a
good use case?

My problem with references in this case is that they look, smell, and feel like a variable that is
part of my own object, but they aren't. This comes into play when you are trying to debug that
access violation when your referenced object is destroyed. A pointer, even a smart pointer, flags
that this object is a separately allocated object and deserves some care. As you could probably
guess, I don't really ever like references as member variables and this is why.
Could someone tell me what advantage would have using weak pointers
instead of plain references?
I don't see any danger here, as the provider class will be destroyed
while the creator is being destroyed. So the provider can be sure that
creator will always exist. Any pitfall here?

The big advantage of weak pointers is that they are guaranteed to either be valid or 0. It also
means that when you get access to the pointer, you have a shared_ptr<> that will keep the object
alive until you are finished with your operation. This removes a lot of worry about the order of
destruction.

What you are guarding against is when some other maintenance programmer comes along and makes some
optimization or tweak. Now the objects aren't destroyed as they were originally designed and
things mysteriously break.

If you don't like all the mechanics of the formal weak pointers, you could just use a raw pointer,
but using typedefs or templates name it something indicating that it is a weak pointer. e.g.

typedef B * weak_B_ptr;

weak_B_ptr pB;

Or something like that.

joe
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top