Referenzen als Funktionsparameter

Moderne Programmierung verwendet sehr viele Funktionsaufrufe. Bisher kennen wir die Übergabe als Instanz (Call-By-Value), bei der eine Kopie des Wertes angelegt wird.

void DrawRectangle( Rectangle rect );

Nehmen wir an, ein Rectangle wäre eine sehr aufwendige Klasse, die beispielsweise ein großes Array kapselt. Möchte man die Instanz kopieren, müsste auch das Array aufwendig kopiert werden.

Also nimmt man den Zeiger auf die Klasse und kopiert diesen in die Parameterliste:

void DrawRectangle( Rectangle * rect );

Nun muss man nicht mehr die Klasse aufwendig kopieren, doch kann ein Zeiger auch auf NULL zeigen oder auf einen ungültigen Speicherbereich. Manche Funktionen erlauben, dass NULL-Pointer übergeben werden - manche nicht. Möchte man kein Risiko eingehen, muss man auf NULL-Pointer überprüfen:

void DrawRectangle( Rectangle * rect )
{
  if( rect != NULL )
  {
    ...    
  }
}

Nehmen wir nun an, dass die Funktion DrawRectangle nun weitere Funktionen ruft, die ebenfalls einen Zeiger auf das Rectangle erhalten - und nun ebenso erstmal prüfen, ob der Zeiger kein Null-Zeiger ist. Am Schluss muss man also sehr vieles doppelt und dreifach prüfen, oder sehr diszipliniert arbeiten, um zu kontrollieren, wo auf den Null-Pointer geprüft wird und welche Funktionen nur von Funktionen gerufen werden dürfen, die garantieren, dass kein Null-Pointer übergeben wird.

Die bessere Alternative ist, dem Compiler die Kontrolle zu überlassen. Hierfür nimmt man die Referenz:

void DrawRectangle( Rectangle & rect )
...
 
int main( void )
{
  Rectangle myRect;
 
  DrawRectangle( myRect );
//  DrawRectangle( NULL );  // <- das geht nicht
 
  return EXIT_SUCCESS;
}

Hier wird in wie bei einem Zeiger nur die Adresse von myRect übergeben, aber die Funktion DrawRectangle kann davon ausgehen, dass es kein Nullpointer ist und auch alle Funktionen, die nun gerufen werden und ebenfalls Referenzen nutzen, können sich die Prüfung auf NULL ebenso sparen.

Referenzen helfen also klar zu unterscheiden, ob eine Funktion einen Nullpointer erlaubt - nämlich wenn sie einen Zeiger erwartet - oder ob sie die Adresse einer real existierende Instanz erwartet: in dem Fall sollte die Referenz verwendet werden.

Diese Form der Übergabe wird Call-By-Reference genannt.

Wer einen Zeiger übergeben möchte, kann auch hier eine Referenz auf den Zeiger nehmen:

bool CreateSomething( Something *& result );