Übergabe eines modifizierbaren Parameters an die C ++ Funktion

7

Vorausgesetzt, ich möchte einen veränderbaren Parameter an eine Funktion übergeben, was soll ich wählen: um es per Zeiger zu übergeben oder um es als Referenz zu übergeben?

  1. bool GetFoo (Foo und whereToPlaceResult);
  2. bool GetFoo (Foo * whereToPlaceResult);

Ich frage das, weil ich es immer als die beste Methode ansah, Parameter durch Verweis (1) zu übergeben, aber nach der Untersuchung einiger lokaler Codedatenbanken kam ich zu dem Schluss, dass der gebräuchlichste Weg (2) ist. Außerdem empfiehlt der Mann selbst (Bjarne Stroustrup), (2) zu verwenden. Was sind die Vorteile von (1) und (2) oder ist es nur eine Frage des persönlichen Geschmacks?

    
SadSido 24.08.2009, 13:44
quelle

12 Antworten

21

Ich bevorzuge eine Referenz anstelle eines Zeigers, wenn:

  • Es kann nicht null sein
  • Es kann nicht geändert werden (um auf etwas anderes hinzuweisen)
  • Es darf nicht gelöscht werden (durch wen auch immer der Zeiger erhält)

Einige Leute sagen jedoch, dass der Unterschied zwischen einer Referenz und einer const-Referenz für viele Menschen zu subtil ist und im Code, der die Methode aufruft, unsichtbar ist (dh, wenn Sie den aufrufenden Code lesen, der einen Parameter als Referenz übergibt, Sie können nicht sehen, ob es eine const oder eine nicht-const Referenz ist), und deshalb sollten Sie es zu einem Zeiger machen (um es im aufrufenden Code explizit zu machen, dass Sie die Adresse Ihrer Variablen weggeben, und deshalb Der Wert Ihrer Variablen kann vom Aufgerufenen geändert werden.)

Ich persönlich bevorzuge eine Referenz, aus folgendem Grund:

  1. Ich denke, dass eine Routine wissen sollte, welche Subroutine sie aufruft
  2. Eine Subroutine sollte nichts davon annehmen, von welcher Routine sie aufgerufen wird.

[1.] bedeutet, dass es für den Aufrufer nicht von Bedeutung ist, die Veränderlichkeit sichtbar zu machen, da der Aufrufer bereits (auf andere Weise) verstehen sollte, was das Unterprogramm tut (einschließlich der Tatsache, dass es den Parameter ändert) / p>

[2.] impliziert, dass, wenn es ein Zeiger ist, die Subroutine die Möglichkeit behandeln sollte, dass der Parameter ein Null-Zeiger ist, der ein zusätzlicher und IMO nutzloser Code sein kann.

Außerdem denke ich, wann immer ich einen Zeiger sehe, "wer wird das löschen und wann?", also wann immer / wo Eigentümerschaft / Lebensdauer / Löschung kein Problem ist, bevorzuge ich eine Referenz.

Für das, was es wert ist, habe ich die Angewohnheit, const-correct-Code zu schreiben: Wenn ich also feststelle, dass eine Methode einen nichtkonstanten Referenzparameter hat, ist die Tatsache, dass sie nicht-const ist, signifikant. Wenn Leute nicht const-korrekten Code schreiben würden, wäre es vielleicht schwieriger zu sagen, ob ein Parameter in einer Subroutine modifiziert wird, und das Argument für einen anderen Mechanismus (z. B. ein Zeiger anstelle einer Referenz) wäre ein bisschen stärker / p>     

ChrisW 24.08.2009, 13:48
quelle
5

Vorteile der Weitergabe als Referenz:

  • Erzwingt, dass Benutzer einen Wert angeben.
  • Weniger fehleranfällig: Verarbeitet den Zeiger selbst. Sie müssen nicht nach innen nach Null suchen.
  • Macht den aufrufenden Code viel sauberer.

Vorteile beim Übergeben von Zeiger nach Wert:

  • Erlaubt die Übergabe von null für "optionale" Parameter. Irgendwie ein hässlicher Hack, aber manchmal nützlich.
  • Zwingt den Anrufer zu wissen, was mit dem Parameter getan wird.
  • Gibt dem Leser einen Hinweis darauf, was mit dem Parameter getan werden könnte, ohne die API lesen zu müssen.

Da die Referenzübergabe in der Sprache erfolgt, werden möglicherweise auch Nicht-Zeiger-Parameter geändert, und Sie wissen nicht, dass Zeigerwerte geändert werden. Ich habe APIs gesehen, wo sie als Konstanten behandelt werden. Die Zeigerübergabe gibt den Lesern also keine Informationen, auf die sie sich verlassen können. Für manche Leute ist das gut genug, aber für mich ist es nicht gut.

Wirklich, Zeigerübergabe ist nur ein fehleranfälliges, unordentliches Hack-Überbleibsel von C, das keine andere Möglichkeit hatte, Werte als Referenz zu übergeben. C ++ hat einen Weg, so dass der Hack nicht mehr benötigt wird.

    
T.E.D. 24.08.2009 14:29
quelle
4

Ein Vorteil bei der Weitergabe durch Referenz besteht darin, dass sie nicht null sein können (im Gegensatz zu Zeigern), wodurch die Notwendigkeit entfällt, alle out-Parameter zu überprüfen.

    
luke 24.08.2009 13:48
quelle
3

Ich würde empfehlen, dass Sie in Erwägung ziehen, (möglicherweise nicht für jede Situation am besten) Foo von der Funktion zurückzugeben, anstatt einen Parameter zu ändern. Ihr Funktionsprototyp würde so aussehen:

%Vor%

Wenn Sie scheinbar ein Erfolgs- / Fehler-Flag zurückgeben, ist die Verwendung einer Ausnahme möglicherweise eine bessere Strategie.

Vorteile:

  • Sie vermeiden alle Pointer- / Referenzprobleme
  • Vereinfacht das Leben für den Anrufer. Kann den Rückgabewert an andere Funktionen übergeben, ohne beispielsweise eine lokale Variable zu verwenden.
  • Der Anrufer kann den Fehlerstatus nicht ignorieren, wenn Sie eine Ausnahme auslösen.
  • Die Rückgabewertoptimierung bedeutet, dass sie genauso effizient sein kann wie das Ändern eines Parameters.
Fred Larson 24.08.2009 14:51
quelle
1

Ich wähle # 2, weil es offensichtlich ist, dass der Parameter geändert wird.

GetFoo (& amp; var) anstelle von GetFoo (var)

Ich bevorzuge die Übergabe durch Verweis nur für Const-Referenzen, wobei ich versuche, einen Kopierkonstruktor-Aufruf zu vermeiden.

    
Lou Franco 24.08.2009 13:48
quelle
1

Übergeben Sie als Referenz und vermeiden Sie das gesamte NULL-Pointer-Problem.

    
Rik Heywood 24.08.2009 13:49
quelle
0

Ich erinnere mich, dass in C ++ Referenzen, wo nicht Null und Zeiger sein könnten. Jetzt habe ich C ++ für eine lange Zeit nicht getan, so dass mein Gedächtnis rostig sein könnte.

    
Preet Sangha 24.08.2009 13:48
quelle
0

Der Unterschied ist hier relativ gering.

Eine Referenz darf nicht NULL sein.

Ein Nullzeiger kann übergeben werden. So können Sie überprüfen, ob das passiert und entsprechend reagieren.

Ich persönlich kann mir keinen wirklichen Vorteil einer der beiden Möglichkeiten vorstellen.

    
StampedeXV 24.08.2009 13:49
quelle
0

Ich finde das eine Frage des persönlichen Geschmacks. Ich ziehe es tatsächlich vor, durch Verweis zu gehen, weil Zeiger mehr Freiheit geben, aber sie neigen auch dazu, eine Menge Probleme zu verursachen.

    
erelender 24.08.2009 13:50
quelle
0

Der Vorteil eines Zeigers ist, dass Sie nichts übergeben können, dh. benutze es so, als wäre der Parameter vollständig optional und hätte keine Variable, die der Aufrufer übergibt.

Referenzen sind ansonsten sicherer, wenn Sie einen haben, ist es garantiert vorhanden und beschreibbar (außer natürlich)

Ich denke, es ist eine Frage der Präferenz, aber ich mag es nicht, die beiden zu mischen, da ich denke, dass dies die Pflege und Lesbarkeit Ihres Codes erschwert (besonders, da Ihre 2 Funktionen für den Anrufer gleich aussehen). p>     

gbjbaanb 24.08.2009 13:51
quelle
0

Heute verwende ich const Referenzen für Eingabeparameter und Zeiger für out Parameter. FWIIW, Google C ++ Style Guide empfiehlt den gleichen Ansatz (nicht, dass ich immer einverstanden bin style guide - zum Beispiel verwenden sie keine Ausnahmen, was normalerweise keinen Sinn macht.

    
Nemanja Trifunovic 24.08.2009 15:02
quelle
0

Meine Präferenz ist eine Referenz. Erstens, weil es sich reimt. :) Auch wegen der Probleme, auf die andere Antworten hinweisen: keine Notwendigkeit zur Dereferenzierung und keine Möglichkeit, dass eine Referenz NULL ist. Ein weiterer Grund, den ich nicht erwähnt habe, ist der, dass man beim Anzeigen eines Zeigers nicht sicher sein kann, ob er auf dynamisch zugewiesenen Speicher zeigt oder nicht und man könnte versucht sein, delete aufzurufen. Eine Referenz hingegen vermeidet jegliche Mehrdeutigkeit in Bezug auf die Speicherverwaltung.

Nachdem dies gesagt wurde, gibt es natürlich viele Fälle, in denen das Übergeben eines Zeigers vorzuziehen oder sogar notwendig ist. Wenn Sie im Voraus wissen, dass der Parameter optional ist, dann ist es sehr nützlich, NULL zuzulassen. Ebenso wissen Sie vielleicht im Voraus, dass der Parameter immer dynamisch zugewiesen wird und die Speicherverwaltung funktioniert.

    
Dima 24.08.2009 15:47
quelle

Tags und Links