Gibt es einen subtilen Unterschied zwischen diesen:
void a1(float &b) {
b=1;
};
a1(b);
und
void a1(float *b) {
(*b)=1;
};
a1(&b);
?
Beide machen dasselbe (oder so scheint es aus main ()), aber der erste ist offensichtlich kürzer, jedoch verwendet der größte Teil des Codes, den ich sehe, die zweite Notation. Ist da ein Unterschied? Vielleicht für den Fall, dass es sich um ein Objekt handelt, anstatt zu schweben?
Antworten:
Beide machen dasselbe, aber man verwendet Referenzen und man verwendet Zeiger.
In meiner Antwort hier finden Sie eine umfassende Liste aller Unterschiede .
quelle
Ja. Die
*
Notation besagt, dass das, was auf dem Stapel übergeben wird, ein Zeiger ist, dh eine Adresse von etwas. Das&
sagt, es ist eine Referenz. Der Effekt ist ähnlich, aber nicht identisch:Nehmen wir zwei Fälle:
void examP(int* ip); void examR(int& i); int i;
Wenn ich anrufe
examP
, schreibe ichDies nimmt die Adresse des Elements und übergibt sie an den Stapel. Wenn ich anrufe
examR
,Ich brauche es nicht; jetzt übergibt der Compiler "irgendwie" eine Referenz - was praktisch bedeutet, dass er die Adresse von erhält und übergibt
i
. Auf der Codeseite alsovoid examP(int* ip){ *ip += 1; }
Ich muss sicherstellen, dass der Zeiger dereferenziert wird.
ip += 1
macht etwas ganz anderes.void examR(int& i){ i += 1; }
aktualisiert immer den Wert von
i
.Weitere Informationen finden Sie unter "Call by Reference" im Vergleich zu "Call by Value". Der
&
Begriff gibt C ++ Aufruf als Referenz.quelle
Im ersten Beispiel mit Referenzen wissen Sie, dass
b
dies nicht NULL sein kann. Mit dem Zeigerbeispielb
könnte der NULL-Zeiger sein.Doch diese Note es ist möglich , ein NULL - Objekt über eine Referenz zu übergeben, aber es ist umständlich und die aufgerufene Prozedur übernehmen kann , es ist ein Fehler geschehen:
a1(*(float *)NULL);
quelle
Im zweiten Beispiel der Anrufer dem Variablennamen '&' voranstellen, um die Adresse der Variablen zu übergeben.
Dies kann von Vorteil sein - der Aufrufer kann eine Variable nicht versehentlich ändern, indem er sie als Referenz übergibt, wenn er glaubt, einen Wert zu übergeben.
quelle
Abgesehen von syntaktischem Zucker besteht der einzige wirkliche Unterschied darin, dass ein Funktionsparameter, der ein Zeiger ist, null sein kann. Daher kann die Zeigerversion aussagekräftiger sein, wenn sie den Nullfall richtig behandelt. Der Null-Fall kann auch eine besondere Bedeutung haben. Die Referenzversion kann nur mit Werten des angegebenen Typs ohne Nullfunktion betrieben werden.
quelle
In Ihrem Beispiel tun beide Versionen dasselbe.
Das erste hat den Vorteil, dass es auf der Anrufseite transparent ist. Stellen Sie sich vor, wie es für einen Operator aussehen würde:
cin >> &x;
Und wie hässlich es für einen Swap-Aufruf aussieht
Sie möchten a und b tauschen. Und es sieht viel besser aus, als wenn Sie zuerst die Adresse nehmen müssen. Bjarne stroustrup schreibt übrigens, dass der Hauptgrund für Referenzen die Transparenz war, die auf der Anrufseite hinzugefügt wurde - insbesondere für Betreiber. Sehen Sie auch, wie es nicht mehr offensichtlich ist, ob das Folgende
&a + 10
Würde dem Inhalt von a 10 hinzufügen, den Operator + davon aufrufen oder ob es 10 zu einem temporären Zeiger auf a hinzufügt. Fügen Sie dies zu der Unmöglichkeit hinzu, dass Sie Operatoren nicht nur für eingebaute Operanden (wie einen Zeiger und eine Ganzzahl) überladen können. Referenzen machen dies kristallklar.
Zeiger sind nützlich, wenn Sie eine "Null" setzen möchten:
a1(0);
Dann kann die Methode in a1 den Zeiger mit 0 vergleichen und sehen, ob der Zeiger auf ein Objekt zeigt.
quelle
Ein großer Unterschied ist, was draußen los ist. Sie haben entweder:
oder:
Ich mag es, Argumente als Referenz zu übergeben (immer eine konstante :)), wenn sie in der Funktion / Methode nicht geändert wurden (und dann können Sie auch automatische / temporäre Objekte darin übergeben) und sie per Zeiger übergeben, um den Benutzer zu kennzeichnen und zu alarmieren. Leser des Codes, der die Methode aufruft, mit der das Argument möglicherweise absichtlich geändert wird.
quelle