views:

402

answers:

3

I'm doing (something like) this:

void insert(Node*& node, string val, Node* parent)
{
   if (node == NULL)
     instantiateNode(node, val, parent);
   else
     insert(node->child, val, node);
}

The thing is, that instantiateNode(..., parent) seems to modify the original *&node passed into the function when setting the *parent. instantiateNode() is supposed to alter the node, but if it alters the parent than you have a node that is set to its parent, which doesn't make sense, and also doesn't work. At all.

The reason I'm bothering with pointer references at all is because it eliminates special cases and significantly reduces the amount of error checking I have to do. Since I'm doing it to reduce line count and trivial algorithm-ish duplication, I can get around this by approximately doubling the code line count. But I'd rather not, and I feel like there should be a way to dereference a pointer reference to get a new pointer that points to the same object. And, really, I thought that pass of *&node through *parent should have done it, but apparently gcc is optimizing it out.

+3  A: 

node is a reference to a pointer, which means that if the function sets node, the value passed in is changed. That's how references work.

If you don't want node to change in the calling function, don't make it a reference.

Or have I misunderstood something?

Graeme Perrow
No, you're right: I want node to change. But then I think that when I pass it to `insert()` as `parent` (which is not a reference) it should be copied and `parent` should be a new pointer that points to the same place as `node` did in the previous function.
quodlibetor
But you're not passing `parent` into `insert()`.
Graeme Perrow
`node` becomes the `parent`, because `insert()` operates on the child of the node. The signature: `insert(node, item, parent)`. The call: `insert(node->child, item, node)`
quodlibetor
Sorry, I somehow missed that you are calling `insert` recursively. Yes, the second time insert is called, the `parent` variable in that frame should be the same as the `node` variable in the caller's frame. You can change the thing that `parent` points to (i.e. the contents of the Node structure), but you can't change `parent` itself.
Graeme Perrow
A: 

I don't think node needs to be passed by reference. A simple pointer should do the job. This is because you don't ever need to change it directly. Why are you passing it to instantiateNode()? It will always be NULL, so what good does it do? If instantiateNode() also has its first argument passed as a reference, why? You are passing in the parent, so instantiateNode() can just access the thing node should represent via parent->child. Even if for some reason instantiateNode() does take it's param by reference and it's required to do so, I believe the function will still work if you drop the reference from insert()'s first argument. Whatever instantiateNode() does with that value will simply be lost when the function returns. I'm sorry that's so confusing, but I can't think of a better way to word it.

There's another interpretation of your problem... maybe your call to insert() should read:

insert(node, val, node->child);
rmeador
The code just appears to build a list, it just appends to the lasts nodes child, i.e. where child==0. Supposing thats what it should do it looks fine to me.
Georg Fritzsche
What happens is that I pass it in, and if it's NULL, I set it to a new child. So I'm actually affecting the pointer itself. It could be done with minor acrobatics by doing a whole lot of condition checking, though. The only reason I'm doing it like this is because it's a 3-5 tree, and I don't want to have to check 3-5 things on every loop.
quodlibetor
+3  A: 

there should be a way to dereference a pointer reference to get a new pointer that points to the same object.

Well, how about this?

Node* n = node;

Now you've got a non-reference pointer that points to the same object as node, exactly what you asked for.

I am 95% sure the problem you are facing has nothing to do with references, and everything to do with faulty logic in instantiateNode or your use of it. That's why it would be useful if you gave us more information about what the code is supposed to do, or even posted the code to instantiateNode.

Darryl
You're absolutely right. I think I let myself get caught up in details, but I tried that, early on, and gdb suggests that it is still pointing to the wrong thing. But even doing `Node* n = ` doesn't fix it, so either I'm just out of luck or, more likely, I'm doing something stupid. It's a small function, though, and I've written tons very similar to it, and I've re-written it I don't even know how many times, and etc, and so I still am unsure about what is going on. If I figure it out, I'll be back.
quodlibetor