Maghio
Maghio

Reputation: 385

Recursive void function with *& parameter

I have a problem with this recursive void function:

void ReadBinaryTree(NODE &p)
{
    char ch;
    File.get(ch);
    if (ch != '#')
    {
        NODE p = new Node;
        p->SetFreq(ch);
        ReadBinaryTree(p->Left());
        ReadBinaryTree(p->Right());
    }
    else return;
}

NODE is a pointer to the class Node and File is an ifstream object. Left() and Right() return NODE. The compiler does not accept the p->Left() and p->Right() arguments, the error is:

no know conversion for argument 1 from 'NODE {aka Node*} to 'Node *&

Could you help me? How can I save the pointers to Node during the recursion?

Upvotes: 0

Views: 537

Answers (3)

amnn
amnn

Reputation: 3716

The issue is that p->Left() and p->Right() are r-values and this means you cannot make references of them. The problem arises because p->Left() is returning some value (Of type Node *), which is being copied into the parameter of ReadBinaryTree.

To fix this, your p->Left() and p->Right() functions should return NODE & values (So that your recursion has access to the exact same pointer as is in the parent node, and not just some copy of it).

Also, NODE p = new Node; should just be p = new Node;.

However, can I suggest that you convert this function into one that returns a value? i.e.

NODE ReadBinaryTree(ifstream &File)
{
    char ch; File.get(ch);
    if(ch != '#')
    {
        NODE p = new Node;
        p->setFreq(ch);
        p->Left() = ReadBinaryTree(File);
        p->Right() = ReadBinaryTree(File);

        return p;
    } else return null;
}

This code still needs the left and right accessors to return references.

EDIT: Explanation of why references can't take r-values

p->Left() (the accessor function) is returning a copy of the left pointer. So while the value is the same as p->left (the attribute), the location in memory is different, and importantly, p->Left() has been assigned a temporary memory location, because it is an expression, and it was expecting a variable to be 'put into'. Normally, when you pass the expression into a function, it is 'put into' the parameter it is passed in as, but if that parameter is a reference, it expects there to already be a non-temporary memory location, which it adopts as its own. So, when you pass an expression (which has a temporary memory location) to something expecting a reference, it complains because it was expecting something with an already fixed memory location, for it to adopt.

Upvotes: 0

youdontneedtothankme
youdontneedtothankme

Reputation: 672

ReadBinaryTree needs a reference to a pointer, so that it can update the pointer to point to the newly created object. The problem is that Left() and Right() only returns the address to the child nodes, but not a reference to the pointer where the address is stored.

So you could change the signature of Left() and Right() from:

NODE Left()

to:

NODE & Left()

As a alternative, you could directly pass the pointers where the child nodes are stored, to ReadBinaryTree:

ReadBinaryTree (p->left)

(This naturally assumes there is a member in Node called left)

Upvotes: 0

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385274

Make it so that Left and Right return references. You are trying to pass temporary values into ReadBinaryTree, which don't bind to the non-const reference in the argument list.

Your recursion is broken anyway, since inside the function you're operating on a local NODE p, not the argument. Maybe you meant p = new Node;, though it's hard to tell from this.

Upvotes: 2

Related Questions