4

The question is simple and may has been discussed before, but I could find a clear answer for my case. Assume I pass a pointer object to a function

#include "foo.h"
int main()
{
   foo * aFoo = new foo;
   bar(aFoo);
   delete aFoo;
   aFoo = NULL;
   return 0;
}

Then the function is written like this

void bar (foo *f)
{
  f->insert();
}

The question:

Is that a call by value or call by reference? I know in call by value, there is an overhead for copying the object from main() to bar(). So I want to be sure that is a call by reference.

mahmood
  • 23,197
  • 49
  • 147
  • 242
  • Aside from your question: Why are you dynamically allocating (and never deleting `aFoo`? `foo aFoo bar(&aFoo)` would have been less problematic – Grizzly Jun 13 '13 at 17:42
  • So why exactly do you allocate `aFoo` dynamically? – Grizzly Jun 14 '13 at 14:53

2 Answers2

11

It is a call by value, where the value of the pointer aFoo is being copied into the function parameter f.

A call by reference is a call where the parameter is a reference, and side-effects on the argument (and not on objects possibly pointed to by that argument) which occur inside the function are visible to the caller when the function returns.

So for instance this is a function accepting a parameter by reference:

void bar(foo*& f)
//           ^
//           Here you are taking a pointer by reference

While this is a function accepting a parameter by value:

void bar(foo* f)
//          ^
//          Here you are taking a pointer to foo by value

You are probably puzzled by the fact that taking a foo by reference and writing:

void bar(foo& f)
{
    f.insert();
}

Has pretty much the same effect as passing a pointer to the same foo object by value and writing:

void bar(foo* f)
{ // Precondition: f != nullptr
    f->insert();
}

However, the two things are conceptually different. While the value/state of the object you passed in the first case can be different when the function returns from the value/state it had before calling the function, in the second case the value of the pointer you provided will be the same as it was before you called bar() - while the object pointed to may have undergone some state change.

Also notice, that a pointer can be null, while a reference is always bound to an object.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • With the second one, then I cannot use "f->insert()". Right? – mahmood Jun 13 '13 at 17:45
  • No but `f.insert()`. You must call bar like this in your example to use call by reference: `bar(*aFoo);`. – Pixelchemist Jun 13 '13 at 17:46
  • @mahmood: No, you have to use `f.insert()`. The important thing is to notice that when you pass an argument by reference your argument can be modified inside the function, and it may have a different value when the function returns than it had before you called it. Notice, that I mean the argument itself, and not the object pointed to by the argument. If you pass a pointer by value and the pointer points to a certain object `x1`, it will still point to `x1` after the function returns, because the function (whatever it did) worked with a *copy* of that pointer – Andy Prowl Jun 13 '13 at 17:52
1

In your case, it is call by value in terms of the pointer to Foo formally. But since you pass a pointer to a function instead of the class instance itself, then it is conceptually call by reference in terms of the class instance since the function call does not copy the whole instance but just its pointer.

Foo fooInstance;
// providing a way to point (less formally you can call it refer) to the instance
Foo* fooPointer = &fooInstance;

// this function call is call by value (passing the value of the pointer).
// but you can logically view it as 'call by reference' to fooInstance.
bar(fooPointer); 
keelar
  • 5,814
  • 7
  • 40
  • 79