C++ Functions – Why Not All Function Parameters Should Be References

cfunctionsparameterspointers

I am currently learning C++ from the C++ Primer 5th edition. The book's chapter on functions states that only large objects (large being relative as standard library strings count, but "primitive types" such as int or char don't) should be passed as references.

For instance, the following function serves as an example in the book on when to use reference parameters:

string::size_type find_char(const string &s, char c, string::size_type &occurs){
    /* code to return the first occurrence of c in s, occurs contains total number of occurrences */
}

One of the exercises asks what the rationale for each of the parameter being what it is beyond it's base type. I understand why the string is a reference (to prevent copying of to improve performance) and why it is const (as it doesn't need to be modified). I also understand why the occurs parameter is a reference (as the original variable's value needs to be changed).

What I don't understand is why c isn't a (const) reference. I know that it contains a very small object, but, wouldn't the prevention of any object from being copied, no matter how small, still be a performance improvement?

If there was some downside to using references, then it would make sense. But, I have no idea what such a downside would be. Also, I know that a pointer's address would be copied, but, since references can't be changed I imagine that the called function could access the original variable in exactly the same way that the caller does (assuming that the variable is declared in the caller).

Why should a non-reference parameter ever be used, especially in instances like the above example, unless the parameter needs to be modified for the function's implementation without returning the changed value?

NOTE: The function body is included in the book, but, is removed from this question for brevity.

Best Answer

For basic types, reference parameters usually offer no performance attribute at all.

Memory

For instance, in your example, the char requires a single byte. A reference type requires a pointer, which is usually either 4 or 8 bytes, where the size of a pointer directly correlates to the type of executable you are using (4 bytes for 32 bit, 8 bytes for 64 bit), due to the size of the memory register.

For most modern machines, this will be passed either on the stack, or in a register, as a single value. So it really makes no difference at all.

Time

Copying a basic type (char, int, long) is usually a single MOV instruction. Setting the pointer used in a reference parameter is, again, usually a single MOV instruction.