Was wäre besser, wenn Sie einer Funktion die ursprüngliche Variable geben, mit der sie arbeiten soll:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
oder:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: Gibt es einen Grund, einen über den anderen zu wählen?
Antworten:
Meine Faustregel lautet:
Verwenden Sie Zeiger, wenn Sie mit ihnen Zeigerarithmetik betreiben möchten (z. B. Inkrementieren der Zeigeradresse, um ein Array zu durchlaufen) oder wenn Sie jemals einen NULL-Zeiger übergeben müssen.
Verwenden Sie anderweitig Referenzen.
quelle
Base* b = new Derived()
)? Dies scheint ein Fall zu sein, der ohne Zeiger nicht behandelt werden kann.Ich denke wirklich, dass Sie von der Einrichtung der folgenden Codierungsrichtlinien für Funktionsaufrufe profitieren werden:
const
Seien Sie wie an allen anderen Orten immer korrekt.const
Bezeichner nicht haben können.Übergeben Sie einen Wert nur per Zeiger, wenn der Wert 0 / NULL im aktuellen Kontext eine gültige Eingabe ist.
Begründung 1: Als Anrufer sehen Sie, dass sich alles, was Sie übergeben , in einem brauchbaren Zustand befinden muss.
Rationale 2: Wie genannt , Sie wissen , dass das, was kommt ist in einem benutzbaren Zustand. Daher muss für diesen Wert keine NULL-Prüfung oder Fehlerbehandlung durchgeführt werden.
Begründung 3: Die Rationales 1 und 2 werden vom Compiler durchgesetzt . Fangen Sie Fehler immer beim Kompilieren ab, wenn Sie können.
Wenn ein Funktionsargument ein Out-Wert ist, übergeben Sie ihn als Referenz.
Wählen Sie "Wert übergeben" anstelle von "Konstante übergeben " nur, wenn der Wert ein POD ( Plain old Datastructure ) oder klein genug (speichertechnisch) oder auf andere Weise billig genug (zeitlich) zum Kopieren ist.
quelle
std::vector<>
.Dies ist letztendlich subjektiv. Die bisherige Diskussion ist nützlich, aber ich glaube nicht, dass es eine richtige oder entscheidende Antwort darauf gibt. Viel hängt von den Stilrichtlinien und Ihren jeweiligen Bedürfnissen ab.
Während es mit einem Zeiger einige verschiedene Funktionen gibt (unabhängig davon, ob etwas NULL sein kann oder nicht), besteht der größte praktische Unterschied für einen Ausgabeparameter in der reinen Syntax. Der C ++ - Style Guide von Google ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ) schreibt beispielsweise nur Zeiger für Ausgabeparameter vor und lässt nur Verweise zu, die const sind. Die Argumentation ist Lesbarkeit: Etwas mit Wertsyntax sollte keine zeigersemantische Bedeutung haben. Ich behaupte nicht, dass dies notwendigerweise richtig oder falsch ist, aber ich denke, der Punkt hier ist, dass es um Stil geht, nicht um Korrektheit.
quelle
Sie sollten einen Zeiger übergeben, wenn Sie den Wert der Variablen ändern möchten. Obwohl die technische Übergabe einer Referenz oder eines Zeigers identisch ist, ist die Übergabe eines Zeigers in Ihrem Anwendungsfall besser lesbar, da dadurch die Tatsache "angekündigt" wird, dass der Wert von der Funktion geändert wird.
quelle
const
oder ohneconst
Referenz akzeptiert , aber Sie können sehen, ob der Parameter ala&x
vs. übergeben wurdex
, und verwenden diese Konvension, um zu kodieren, ob der Parameter geändert werden kann. (Das heißt, es gibt Zeiten, in denen Sie einenconst
Zeiger übergeben möchten , daher ist die Konvension nur ein Hinweis. Der Verdacht, dass etwas geändert werden könnte, wenn es nicht sein wird, ist weniger gefährlich als der Gedanke, dass es nicht sein wird, wenn es sein wird ....)Wenn Sie einen Parameter haben, bei dem Sie möglicherweise das Fehlen eines Werts angeben müssen, ist es üblich, den Parameter zu einem Zeigerwert zu machen und NULL zu übergeben.
Eine bessere Lösung in den meisten Fällen (aus Sicherheitsgründen) ist die Verwendung von boost :: optional . Auf diese Weise können Sie optionale Werte als Referenz und auch als Rückgabewert übergeben.
quelle
Verwenden Sie eine Referenz, wenn Sie können, und verwenden Sie einen Zeiger, wenn Sie müssen. In den C ++ - FAQ: "Wann sollte ich Referenzen verwenden und wann sollte ich Zeiger verwenden?"
quelle
Zeiger
Ein Zeiger, der derzeit nicht auf einen gültigen Speicherort zeigt, erhält den Wert null (was null ist).
Das & ist ein unärer Operator, der die Speicheradresse seines Operanden zurückgibt.
Der Dereferenzierungsoperator (*) wird verwendet, um auf den Wert zuzugreifen, der in der Variablen gespeichert ist, auf die der Zeiger zeigt.
Referenz
Eine Referenz (&) ist wie ein Alias für eine vorhandene Variable.
Eine Referenz (&) ist wie ein konstanter Zeiger, der automatisch dereferenziert wird.
Es wird normalerweise für Funktionsargumentlisten und Funktionsrückgabewerte verwendet.
Eine Referenz muss beim Erstellen initialisiert werden.
Sobald eine Referenz auf ein Objekt initialisiert wurde, kann sie nicht mehr geändert werden, um auf ein anderes Objekt zu verweisen.
Sie können keine NULL-Referenzen haben.
Eine const-Referenz kann sich auf eine const int beziehen. Dies erfolgt mit einer temporären Variablen mit dem Wert const
quelle
Eine Referenz ist ein impliziter Zeiger. Grundsätzlich können Sie den Wert ändern, auf den die Referenz zeigt, aber Sie können die Referenz nicht ändern, um auf etwas anderes zu zeigen. Meine 2 Cent sind also: Wenn Sie nur den Wert eines Parameters ändern möchten, übergeben Sie ihn als Referenz, aber wenn Sie den Parameter ändern müssen, um auf ein anderes Objekt zu zeigen, übergeben Sie ihn mit einem Zeiger.
quelle
Betrachten Sie das Schlüsselwort out von C #. Der Compiler verlangt vom Aufrufer einer Methode, dass er das Schlüsselwort out auf alle out-Argumente anwendet, obwohl er bereits weiß, ob dies der Fall ist. Dies soll die Lesbarkeit verbessern. Obwohl ich bei modernen IDEs eher der Meinung bin, dass dies ein Job für die Hervorhebung von Syntax (oder Semantik) ist.
quelle
Übergeben Sie die Konstantenreferenz, es sei denn, es gibt einen Grund, warum Sie den Inhalt, den Sie übergeben, ändern / behalten möchten.
Dies ist in den meisten Fällen die effizienteste Methode.
Stellen Sie sicher, dass Sie const für jeden Parameter verwenden, den Sie nicht ändern möchten, da dies Sie nicht nur davor schützt, etwas Dummes in der Funktion zu tun, sondern auch anderen Benutzern einen guten Hinweis darauf gibt, was die Funktion mit den übergebenen Werten macht. Dazu gehört das Erstellen einer Zeigerkonstante, wenn Sie nur ändern möchten, auf was ...
quelle
Zeiger:
nullptr
(oderNULL
).&
wenn Ihr Typ selbst kein Zeiger ist, sodass Sie Ihr Objekt explizit ändern.Verweise:
&
. Dies wird manchmal als schlecht angesehen, da Sie zur Implementierung der Funktion gehen müssen, um festzustellen, ob Ihr Parameter geändert wurde.quelle
Eine Referenz ähnelt einem Zeiger, außer dass Sie kein Präfix ∗ verwenden müssen, um auf den Wert zuzugreifen, auf den sich die Referenz bezieht. Es kann auch nicht darauf verwiesen werden, dass nach seiner Initialisierung auf ein anderes Objekt verwiesen wird.
Referenzen sind besonders nützlich, um Funktionsargumente anzugeben.
Weitere Informationen finden Sie unter "Eine Tour durch C ++" von "Bjarne Stroustrup" (2014), Seiten 11-12
quelle