DIMAJIX - software consulting (http://www.dimajix.de/)
 

Function Parameters


Rule 28. Do not use functions with many arguments.

Functions with many arguments look complicated, are difficult to read, and can indicate poor design. In addition, they are difficult to use and to maintain. You might consider to create a class instead that has specific setters and getters for the various arguments and a method that does the real work after all parameters have been set.


Rule 29. Use constant references (const &) instead of call-by-value, unless using a pre-defined data type or a pointer.

This rule helps to improve performance, because if you pass big objects directly as a parameter, the complete object probably will be copied onto the stack using a constructor and after the function is called the duplicate will be destroyed using a destructor. In order to avoid these expensive and in most cases unnecessary operations, you should prefer using a const reference for passing objects. The following example should explain this further.

class BigComplexClass { ... };

void f1(BigComplexClass );
void f2(const BigComplexClass& );

...

BigComplexClass bigObject;
f1(bigObject);      // Has to copy the object. Expensive!
f2(bigObject);      // Essentially passes only a const pointer. Cheap.

The const declaration is very important, because normally you would not want the functions f1 and f2 to modify the original object bigObject. Actually since f1 gets only a copy of the object, it has no chance to modify the object bigObject at all. In most cases this is the desired behaviour.

Of course there is also the possibility to pass a pointer to an object to a function or method. The question whether to use a pointer or a reference will be answered in the next rules.

Rule 30. If a parameter of a function or method is an object, which is not modified, pass it by const reference.

This rule may seem to be the same as the last one, but its emphasis is on the fact the the object is not modified. In this case you should use a const reference instead of a pointer as a rule of the thumb. But again, there are many situations where a const pointer seems to be more appropriate, although technically they are just the same.


Exception to 30. If an object typically is created as a pointer, it is preferred to pass it by pointer.

If you work with a class whose objects are typically created using new or another dynamic allocation mechanism in contrast to a simple construction on the stack, then it is more natural to work with pointers as opposed to references. But again, if the object whose pointer is passed to a function is not to be modified by the function, you should use a const pointer.


Rule 31. Never use non-const references as parameters. If a parameter of a function or method is an object, which is modified, pass it by pointer.

Consider the following piece of code:

class C { ... };

void f1(C );
void f2(C& );

...

C object;
f1(object);      // f1 cannot modify object, it works on a copy
f2(object);      // f2 can modify object, it works directly on object

Although both function invocations semantically look the same, they can have very different effects on object. Because f1 was called with a complete copy of object and is therefore working with a duplicate, it cannot modify the contents of object. On the other hand, f2 works with a reference to object itself, so any modifications remain after f1 returns.

The fact that one cannot see this difference by looking at the invocation, and that one normally thinks in terms of call-by-value makes the function f2 dangerous, because one might expect that it does not modify object.

In order to sensitise the caller of a function that has side-effects on its parameters, it is better to pass the object by a non-const pointer. The example above should be rewritten as

class C { ... };

void f1(const C& );
void f2(C* );

...

C object;
f1(object);      // f1 does not modify object, it uses a const reference
f2(&object);     // f2 can modify object, it uses a pointer

So every time the programmer is forced to use the pointer operator (&), he should be aware that the function might modify the corresponding object.


Rule 32. Do not use unspecified function arguments (ellipsis notation).

One of the best known function which uses unspecified arguments is printf. But these functions lack the strong type checking provided by C++ and is thereby avoided.

Kaya Memisoglu 2005-01-06