views:

85

answers:

3

This is a noobie question, but I'm not sure how to pass by reference in C++. I have the following class which sets up a Node and a few functions.

class Node
{
  public:
    Node *next;
    int data;
    Node(int dat)
    {
      next = NULL;
      data = dat;
    }
    Node* getNext()
    { return next; }
    void setNext(Node *n)
    { next = n;}

    void reverse(Node *root)
    {
      Node *previous = NULL;
      while(root != NULL)
      {
        Node *next = root->getNext();
        root->setNext(previous);
        previous = root;
        root = next;
      }
      root = previous;
    }
};

Now, the purpose of my little class is to create a singularly linked list and have the ability to reverse it. And it seems to work fine, if I return the node named 'previous' at the end of reverse.

But look at my main function:

int main()
{
  Node *root = new Node(1);
  Node *num2 = new Node(2);
  Node *num3 = new Node(3);
  Node *num4 = new Node(4);

  root->setNext(num2);
  num2->setNext(num3);
  num3->setNext(num4);
  root->printList();
  root->reverse(root);
  root->printList();

  return 0;
}

printList() was omitted for sake of space, but it just prints a list given a node. The problem is, when root->reverse(root) is called, root doesn't actually end up pointing to 'previous'.

The output would be this:

1
2
3
4
  // the value of previous from the reverse function is 4
1

I really don't understand the output. Anyone care to explain what's happening? (Why isn't the list reversed even though if I did something like this root = root->reverse(root) where reverse returns previous, it would) why is it that root now only points to itself? I'm new to c++ and appreciate your help!

+3  A: 

C++ has support for reference semantics. Therefore, for a given function:

void foo(Bar& bar);

To pass by reference you do:

int main() {
  Bar whatsit;

  foo(whatsit);

  return 0;
}

That's it!

This is commonly confused with passing a pointer, where for a function such as:

void foo(Bar* bar);

You would do:

int main() {
  Bar whatisit;

  foo(&whatsit);

  return 0;
}

The difference is mostly a matter of semantics: - A reference is always valid. There is no reason to check for a NULL pointer. - A pointer could be NULL, and as such, should be checked.

It is, however, possible for a reference to refer to a NULL pointer, however, if the programmer decides to be evil and abuse reference semantics, but the principle remains.

Arafangion
So I think I understand what you guys mean about passing by value a copy of the pointer. I understand then why reverse(Node* root->reverse(root))
kodai
There, root is a pointer to a Node. It is not a reference.
Arafangion
Changing the parameter to (Node `), calling the function like reverse(root), or keep the pointer and pass the actual Node that the pointer is pointing to, like reverse(*root).
Big Al
+2  A: 

To pass a pointer by reference you can declare reverse as:

void reverse(Node*& root) {
  // ...
}
jbernadas
+2  A: 

You aren't passing by reference. You are passing a copy of the pointer. This copy still points to the same node, but it is still just a copy with local scope. Basically it is another pointer pointing to the node that the pointer in main is pointing to (ha!). At the end of your function, your assignment is assigning previous to this pointer copy, and then the function ends and the copy goes out of scope. Your pointer in main remains unchanged.

The reason returning/assigning the pointer worked is that this copy which has been set to what you want is returned and assigned to your pointer in main.

You can fix this in a multitude of ways. Pass a reference to your pointer (ugly imo), use references, or return root and do an assignment.

Big Al