When Pass-By-Pointer Is Preferred to Pass-By-Reference in C++

When pass-by-pointer is preferred to pass-by-reference in C++?

Some like pass-by-pointer better in cases where the object being passed is actually going to be modified. They use pass-by-const-reference when the object is being passed by reference in order to avoid a copy of the object, but will not be changed in the function.

In illustration, take the following functions:

int foo(int x);
int foo1(int &x);
int foo2(int *x);

Now in the code, I do the following:

int testInt = 0;

foo(testInt); // can't modify testInt
foo1(testInt); // can modify testInt

foo2(&testInt); // can modify testInt

In calling foo vs foo1, it's not apparent from the callers perspective (or a programmer reading the code) that the function can modify testInt without having to look at the signature of the function. Looking at foo2, a reader can easily see that the function may in fact modify the value of testInt because the function is receiving the address of the parameter. Note that this doesn't guarantee the object is actually modified, but that's where being consistent in the use of references vs. pointers helps. In general, if you want to follow this guideline consistently you should always pass const references when you want to avoid copies, and pass by pointer when you want to be able to modify the object.

Are there benefits of passing by pointer over passing by reference in C++?

A pointer can receive a NULL parameter, a reference parameter can not. If there's ever a chance that you could want to pass "no object", then use a pointer instead of a reference.

Also, passing by pointer allows you to explicitly see at the call site whether the object is passed by value or by reference:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

When to pass by reference and when to pass by pointer in C++?

References are easier to get right.

Is your problem with literals that you aren't using const references? You can't bind a temporary (produced by a literal) to a non-const reference, because it makes no sense to change one. You can bind one to a const reference.

In particular, when passing an argument to a function, and the function isn't going to change it, and it isn't a built-in type, pass by const reference. It works much the same as pass by value, except it doesn't require a copy constructor call.

Pointers are useful in that they have a guaranteed invalid value you can test for. Sometimes this is irrelevant, and sometimes it's very important. Of course, you can't generally pass a literal by pointer, unless (in case of a string literal) it already is.

Some coding standards say that nothing should ever be passed by non-const reference, since it provides no indication at the point of call that the argument might be changed by the function. In that case, you will be required to pass by pointer. I don't favor this, particularly as programming tools make it easier and easier to get the function signature, so you can see if a function might change an argument. However, when working in a group or for an enterprise, style consistency is more important than any individual style element.

Reason to Pass a Pointer by Reference in C++?

You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.

This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.

Where should I prefer pass-by-reference or pass-by-value?

There are four main cases where you should use pass-by-reference over pass-by-value:

  1. If you are calling a function that needs to modify its arguments, use pass-by-reference or pass-by-pointer. Otherwise, you’ll get a copy of the argument.
  2. If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit.
  3. If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.
  4. If you're writing a function that wants to operate on a polymorphic class, use pass by reference or pass by pointer to avoid slicing.

Meaning of pass by reference in C and C++?

In colloquial usage, "pass by reference" means that, if the callee modifies its arguments, it affects the caller, because the argument as seen by the callee refers to the value as seen by the caller.

The phrase is used independent of the actual programming language, and how it calls things (pointers, references, whatever).

In C++, call-by-reference can be done with references or pointers. In C, call-by-reference can only be achieved by passing a pointer.

"Call by value":

void foo( int x )
{
// x is a *copy* of whatever argument foo() was called with
x = 42;
}

int main()
{
int a = 0;
foo( a );
// at this point, a == 0
}

"Call by reference", C style:

void foo( int * x )
{
// x is still a *copy* of foo()'s argument, but that copy *refers* to
// the value as seen by the caller
*x = 42;
}

int main()
{
int a = 0;
foo( &a );
// at this point, a == 42
}

So, strictly speaking, there is no pass-by-reference in C. You either pass the variable by-value, or you pass a pointer to that variable by-value.

Pass by pointer & Pass by reference

A reference is semantically the following:

T& <=> *(T * const)

const T& <=> *(T const * const)

T&& <=> [no C equivalent] (C++11)

As with other answers, the following from the C++ FAQ is the one-line answer: references when possible, pointers when needed.

An advantage over pointers is that you need explicit casting in order to pass NULL.
It's still possible, though.
Of the compilers I've tested, none emit a warning for the following:

int* p() {
return 0;
}
void x(int& y) {
y = 1;
}
int main() {
x(*p());
}

Is passing pointer argument, pass by value in C++?

Yes to both.

Pointers are passed by value as anything else. That means the contents of the pointer variable (the address of the object pointed to) is copied. That means that if you change the value of the pointer in the function body, that change will not be reflected in the external pointer that will still point to the old object. But you can change the value of the object pointed to.

If you want to reflect changes made to the pointer to the external pointer (make it point to something else), you need two levels of indirection (pointer to pointer). When calling functions it's done by putting a & before the name of the pointer. It is the standard C way of doing things.

When using C++, using references is preferred to pointer (henceforth also to pointer to pointer).

For the why references should be preferred to pointers, there is several reasons:

  • references introduce less syntaxic noise than pointers in function body
  • references keep more informations than pointers, than can be useful for compiler

Drawbacks of references are mostly:

  • they break the simple pass-by-value rule of C, what makes understanding the behavior of a function regarding of parameters (will they be changed ?) less obvious. You also need function prototype to be sure. But that is not really worse than the multiple pointer levels necessary when using C.
  • they are not supported by C, that can be a problem when you write code that should work with both C and C++ programs (but that's not the most usual case).

In the specific case of pointer to pointer, the difference is mostly simplicity, but using reference it may also be easy to remove both levels of pointers and pass only one reference instead of a pointer to pointer.

Performance cost of passing by value vs. by reference or by pointer?

It depends on what you mean by "cost", and properties of the host system (hardware, operating system) with respect to operations.

If your cost measure is memory usage, then the calculation of cost is obvious - add up the sizes of whatever is being copied.

If your measure is execution speed (or "efficiency") then the game is different. Hardware (and operating systems and compiler) tend to be optimised for performance of operations on copying things of particular sizes, by virtue of dedicated circuits (machine registers, and how they are used).

It is common, for example, for a machine to have an architecture (machine registers, memory architecture, etc) which result in a "sweet spot" - copying variables of some size is most "efficient", but copying larger OR SMALLER variables is less so. Larger variables will cost more to copy, because there may be a need to do multiple copies of smaller chunks. Smaller ones may also cost more, because the compiler needs to copy the smaller value into a larger variable (or register), do the operations on it, then copy the value back.

Examples with floating point include some cray supercomputers, which natively support double precision floating point (aka double in C++), and all operations on single precision (aka float in C++) are emulated in software. Some older 32-bit x86 CPUs also worked internally with 32-bit integers, and operations on 16-bit integers required more clock cycles due to translation to/from 32-bit (this is not true with more modern 32-bit or 64-bit x86 processors, as they allow copying 16-bit integers to/from 32-bit registers, and operating on them, with fewer such penalties).

It is a bit of a no-brainer that copying a very large structure by value will be less efficient than creating and copying its address. But, because of factors like the above, the cross-over point between "best to copy something of that size by value" and "best to pass its address" is less clear.

Pointers and references tend to be implemented in a similar manner (e.g. pass by reference can be implemented in the same way as passing a pointer) but that is not guaranteed.

The only way to be sure is to measure it. And realise that the measurements will vary between systems.



Related Topics



Leave a reply



Submit