I can imagine one case, in which the input parameter could be NULL so that pass-by-pointer is preferred but not pass-by-reference?
Can anybody add more cases?
If I need to pass an array of objects, I need to pass by pointer. Arrays aren't always stored in std::vector<>
.
Other than that, pass by pointer allows NULL and pass by reference doesn't, so I use that distinction as a contract much like NULL
vs. NOT NULL
columns in SQL, and loosely like "function returning bool
: true
= succeeded and false
= failed, vs. function returning int
: return value is a result code where 0
= success and others are failures".
Rule number one for this: If NULL is a valid value for the function parameter in the context of the function, then pass it as pointer, otherwise pass it as reference.
Rationale, if it cannot (should not!) ever be NULL, then don't put yourself through the trouble of checking for NULL or risking problems due to it being NULL.
When dealing with raw memory (for example if creating your own memory pool), you'd want to use a pointer. But you're right, in normal code the only use for a pointer is an optional parameter.
In C++ there's little to no need to pass by pointer in most cases. You should consider first the alternatives: templates, (const) references, containers, strings and smart pointers. That said, if you must support legacy code then you'll need to use pointers. If your compiler is minimalistic (embedded systems, for example) you'll need pointers. If you need to talk to a C library (a system library of some sort for a very particular driver you're working with?) then you'll need to work with pointers. If you want deal with very particular offsets of memory then you'll need pointers.
In C pointers are first-class citizens, they are way too fundamental to think about eliminating them.
Anytime you pass a function pointer. Or if you have a "reset" method a la auto_ptr.
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.