1

While doing some questions based on binary search trees...I got little confused in a function call:

void find(node* root,node*& temp)
{
     blah blah...
}
int main()
{
     node* temp=NULL;
     node* root=NULL; 
     find(root,temp);
}

What is the difference between both the passed arguments?

Christophe
  • 68,716
  • 7
  • 72
  • 138
Qazazaz
  • 120
  • 1
  • 1
  • 14

4 Answers4

2

In

void find(node* root,node*& temp)

root is passed by value. Anything you do to *root will be reflected in the caller but any change to root will not.

temp is passed by reference. Anything you do to *temp will be reflected in the caller and any change to temp will also be reflected in the caller.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • so can i make temp globally to use them inside find function instead of passing it to function? – Qazazaz Jan 22 '16 at 20:07
  • @Himanshu You cold but global variables are frowned upon in C++. – NathanOliver Jan 22 '16 at 20:07
  • @NathanOliver, not really, no. Some of those are very much embraced. – SergeyA Jan 22 '16 at 20:11
  • @Himanshu You could always ask another question about that. Make sure you include an [mcve] if you do. – NathanOliver Jan 22 '16 at 20:11
  • @SergeyA The general consensus I have seen is to avoid global variables. There are times and places where they are needed but most of the time they are not. – NathanOliver Jan 22 '16 at 20:12
  • @NathanOliver, how about `cout`? – SergeyA Jan 22 '16 at 20:13
  • @SergeyA Like I said, *generally* they are not needed. `cout` is one of those special exceptions. You can also see: [Are global variables bad?](http://stackoverflow.com/questions/484635/are-global-variables-bad) – NathanOliver Jan 22 '16 at 20:17
  • @NathanOliver, I am well aware of this question. I was just trying to bring attention to the fact that not all of them are frown upon, and there are very legitimate cases to use global vars. Unfortunately, too many times I see people interpreting 'global vars a bad' in a way that 'while singletons are good' - so everything is happily redone into singleton with the same ugliness. – SergeyA Jan 22 '16 at 20:20
2

node *root represents a pointer to a node struct (passed by value). If you change the value, you change a local valriable here.

node *&temp represents a reference to a pointer to a node struct. If you change the value of temp, you modify the original pointer passed by reference.

Christophe
  • 68,716
  • 7
  • 72
  • 138
0

The first pointer function parameter (i.e., node *root) is passed by value (i.e., a copy of the original pointer object is passed in the function) and the second one (i.e., node*& temp) is passed by reference (i.e., an alias of the original pointer is passed in the function).

Consider the following example:

void find(node* root,node*& temp) {
   root = z;
   temp = z;
}

int main() {
  node *root = x;
  node *temp = y;
  find(root, temp);
  // at this point root still points to x
  // temp changed and points to z
}
101010
  • 41,839
  • 11
  • 94
  • 168
0

The & prefix on the identifier being declared makes it a reference. Because the reference isn't const, the argument expression has to be an lvalue (i.e. has to designate an object). The function can modify that object!

If the function doesn't modify the object and you don't try to pass something which isn't an object, such as a null pointer constant, you won't notice any difference.

The declared type doesn't change; either way, the type is node *. A reference isn't a type; it's an aspect of how a name refers to a value.

For instance if we have:

int x = 0, y = 2;

there are two objects. If we declare y as a reference, there is one object of type int, which effectively has two names:

int x = 0, &y = x;

the initializer for the reference is the x object itself, rather than x's value.

When we declare a function parameter as a reference, it becomes a "reference parameter". The way the function receives the value through that parameter changes from the usual "pass by value" semantics inherited from C.

It's also possible to bind references to const types. Const reference parameters are curious; they can receive literal objects as values:

void foo(const int &x);  // can be called as foo(42);  !

Const references are useful because when you pass a const reference to a class object, it resembles "pass by value", but is cheaper because the object itself is passed (no copy construction takes place).

Const references were introduced into C++ to solve the problem of "what should the parameter of a copy constructor be?". A copy constructor cannot look like this:

some_class::some_class(some_class original_obj) { /*...*. }

because this creates a chicken-and-egg problem: passing the object to the copy constructor requires a copy (due to the by-value semantics) which requires a copy constructor! Const reference invention to the rescue:

some_class::some_class(some_class &original_obj) { /*...*. }

Problem solved; the copy constructor receives the object by reference, yet in a way that is quasi-safe because the object is quasi-unmodifiable. (Quasi, because at some point, the mutable keyword was invented to punch holes in const objects.)

Kaz
  • 55,781
  • 9
  • 100
  • 149