[osg-users] Ref_ptr question : argument and return

Thibault Genessay tibogens at gmail.com
Tue Sep 23 00:32:58 PDT 2008


Hi Vincent

On Mon, Sep 22, 2008 at 5:23 PM, Vincent Bourdier
<vincent.bourdier at gmail.com> wrote:
> Hi all,
>
> I read that all the objects that inherit from Referenced need to be in a
> ref_ptr.

They don't _need_ to. You can perfectly use a raw pointer to an
osg::Referenced instance, e.g. create a new node:
MyNode* node = new MyNode();
myscene->addChild(node);
You have to be aware that if an exception is thrown (or any event that
could cause the addChild() call to be skipped) before the node is
added to the parent the memory will not be freed - group nodes keep
ref_ptr<>s to their children, and once the node is added to 'myscene'
it will be managed by the ref_ptr mechanism.

The general rule is to use raw pointers only when you do trivial
things (e.g. creating an instance provided that the constructor cannot
throw) or when you know that your object is already referenced from
somewhere else (e.g. like in osg::Node* node = myscene->getChild(0)).
Use ref_ptrs as class members (*) (e.g. have a look at osg::Group) and
when things are more complicated, especially w.r.t exceptions that
could be thrown in the meantime.

> Ok that sounds good , but :
>
> In this case I don't know if I need to put the ref_prt in argument or if
> only the ptr is needed.

It's not a good idea to use ref_ptr<> in arguments. If your function looks like
void setFooState(ref_ptr<Node> arg) { // add the foo state to the
node's stateset  }
And you call it this way:
osg::Node* node = new MyNode();
setFooState(node);
then a ref_ptr will be implicitly created. It will ref() the node, do
whatever it needs to do with it and unref() it before it returns to
the caller. Since the node was not referenced from somewhere else, it
will be deleted and your 'node' pointer will be a dangling pointer -
which is certainly not what you want.

OTOH, if your function is defined as
void setFooState(osg::Node* arg) {...}
you can safely call either
setFooState(node); if you have a raw pointer to your node
or
setFooState(node.get()); if you have a ref_ptr to your node

Hope this helps

Thibault

(*) Keep in mind that your (scene) graph must be acyclic w.r.t to
ref_ptr<>s: if A holds a ref_ptr to B then neither B nor its children
must hold a ref_ptr to A. This is why Groups have an
std::vector<ref_ptr<Node> > to their children, and Nodes have an
std::vector<Node*> to their parents.



More information about the osg-users mailing list