Question

Which one is better: Pass by Reference using void increment(int& x) or Pass by Pointer using void increment(int* x)?

  1. void increment(int& x)
    {
        x=x+1;
    }
    int main()
    {  
        int n= 2;
        increment(n);
        cout << "Value of n is " << n << '\n';
        return 0;
    }
    

    or

  2. void increment(int* x)
    {
        *x=*x+1;
    }
    int main()
    {  
        int n= 2;
        increment(&n);
        cout << "Value of n is " << n << '\n';
        return 0;
    }
    
Was it helpful?

Solution

None is better. The advantage of using pointer is that it makes explicit in the calling code that the argument is passed by pointer, since the argument is preceded with &. The advantage of using reference is that it is more natural in the calling function code, without all * dereferences. Internally the are normally implemented in the same way, so there should be no speed advantages.

OTHER TIPS

Without knowing what you think "better" means, I can only say they are different.

Pros of passing by reference:

  1. Passing by reference will prevent you from passing nullptr and will make it more difficult to pass an invalid value.

In terms of performance, you're not going to see much, if any, difference.

Pros of passing by pointer:

  1. Passing by reference is not compatible with C, so if you're exposing a function that you expect to be called from C, you'd need to make it pass a pointer.

  2. Passing a pointer allows you pass nullptr/NULL. While listing this as a benefit may seem to contradict listing the inability to do this as a benefit of references, it depends on how you're using your function. If you want to be able to specify that there is no value for a parameter (and don't want to include boost::optional or roll your own), then a pointer is an idiomatic way of doing that.

In this specific case, I would prefer passing by reference, since there's no reason to call the function without a valid value.

My personal rule of thumb:

  • Use pointers for (in/)out parameters, so it's immediately clear that the function will change the variable
  • Use references for normal parameters

So in your case, where the function increment() is clearly altering the passed in variable, I would use a pointer. If you use a reference, somebody reading your code will have to jump to the function's declaration in order to understand the function's side effect.

For an externally facing component (i.e. when writing a library third parties will consume), I would take a pointer, it lets users know you're going to modify what they pass in. This comes at the cost of pointer dereferencing which has a very very minor performance cost - since you will want to check the pointer is not NULL before using it.

For internal functions which aren't meant to be exposed, passing by reference is preferable since it is easier to writer and is (again, only very slightly) more performant.

With clang and no optimisations:

00000000004004c0 <_Z10doThingRefRi>:
  4004c0:       48 89 7c 24 f8          mov    %rdi,-0x8(%rsp)
  4004c5:       48 8b 7c 24 f8          mov    -0x8(%rsp),%rdi
  4004ca:       8b 07                   mov    (%rdi),%eax
  4004cc:       05 01 00 00 00          add    $0x1,%eax
  4004d1:       89 07                   mov    %eax,(%rdi)
  4004d3:       c3                      retq
  4004d4:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  4004db:       00 00 00 00 00

00000000004004e0 <_Z10doThingPtrPi>:
  4004e0:       48 89 7c 24 f8          mov    %rdi,-0x8(%rsp)
  4004e5:       48 81 7c 24 f8 00 00    cmpq   $0x0,-0x8(%rsp)
  4004ec:       00 00
  4004ee:       0f 84 0f 00 00 00       je     400503 <_Z10doThingPtrPi+0x23>
  4004f4:       48 8b 44 24 f8          mov    -0x8(%rsp),%rax
  4004f9:       8b 08                   mov    (%rax),%ecx
  4004fb:       81 c1 01 00 00 00       add    $0x1,%ecx
  400501:       89 08                   mov    %ecx,(%rax)
  400503:       c3                      retq
  400504:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40050b:       00 00 00 00 00

with clang and -O3

00000000004004c0 <_Z10doThingRefRi>:
  4004c0:       ff 07                   incl   (%rdi)
  4004c2:       c3                      retq
  4004c3:       66 66 66 66 2e 0f 1f    data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
  4004ca:       84 00 00 00 00 00

00000000004004d0 <_Z10doThingPtrPi>:
  4004d0:       48 85 ff                test   %rdi,%rdi
  4004d3:       74 02                   je     4004d7 <_Z10doThingPtrPi+0x7>
  4004d5:       ff 07                   incl   (%rdi)
  4004d7:       c3                      retq
  4004d8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  4004df:       00
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top