pointers vs. Referenz

Was wäre besser, wenn man einer function die ursprüngliche Variable gibt, mit der man arbeiten kann:

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?

   

Meine Faustregel ist:

Verwenden Sie pointers, wenn Sie pointersarithmetik mit ihnen durchführen möchten (z. B. die pointersadresse erhöhen, um durch ein Array zu gehen) oder wenn Sie jemals einen NULL-pointers übergeben müssen.

Verwenden Sie Referenzen andernfalls.

Ich denke wirklich, dass Sie davon profitieren werden, die folgende function einzurichten, die Codierungsrichtlinien aufruft:

  1. Wie in allen anderen Orten, immer const correct.

    • Hinweis: Dies bedeutet unter anderem, dass nur out-Werte (siehe Punkt 3) und Werte, die als Wert übergeben wurden (siehe Punkt 4), den const Spezifizierer nicht haben können.
  2. Übergeben Sie nur einen Wert per pointers, wenn der Wert 0 / NULL eine gültige Eingabe im aktuellen Kontext ist.

    • Begründung 1: Als Anrufer sehen Sie, dass alles, was Sie weitergeben , in einem brauchbaren Zustand sein muss.

    • Begründung 2: Wie Sie wissen, wissen Sie, dass alles, was reinkommt, in einem brauchbaren Zustand ist. Daher muss für diesen Wert keine NULL-Prüfung oder Fehlerbehandlung durchgeführt werden.

    • Rationale 3: Die Rationales 1 und 2 werden vom Compiler durchgesetzt . Fangen Sie immer Fehler zur Kompilierzeit, wenn Sie können.

  3. Wenn ein functionsargument ein Out-Wert ist, übergeben Sie es als Referenz.

    • Begründung: Wir wollen nicht Punkt 2 brechen …
  4. Wählen Sie “pass by value” über “pass by const reference” nur, wenn der Wert ein POD ( Plain Old Datastructure ) oder klein genug (speicherweise) oder auf andere Weise billig genug (zeitweise) zum Kopieren ist.

    • Begründung: Vermeiden Sie unnötige Kopien.
    • Hinweis: Klein genug und billig genug sind nicht absolut messbar.

Dies endet letztlich als subjektiv. Die bisherige Diskussion ist nützlich, aber ich glaube nicht, dass es eine richtige oder entscheidende Antwort darauf gibt. Viel hängt von Stilrichtlinien und Ihren Bedürfnissen zu der Zeit ab.

Während es mit einem pointers einige verschiedene Fähigkeiten gibt (ob etwas NULL sein kann oder nicht), ist der größte praktische Unterschied für einen Ausgabeparameter reine Syntax. Der Google C ++ – Style-Guide ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ) beispielsweise schreibt nur pointers für Ausgabeparameter vor und lässt nur Referenzen zu, die const sind. Die Argumentation ist eine der Lesbarkeit: etwas mit Wert-Syntax sollte keine semantische Bedeutung haben. Ich behaupte nicht, dass dies notwendigerweise richtig oder falsch ist, aber ich denke, der Punkt hier ist, dass es eine Frage des Stils ist, nicht der Korrektheit.

Sie sollten einen pointers übergeben, wenn Sie den Wert der Variablen ändern möchten. Auch wenn die Übergabe eines Verweises oder eines pointerss technisch identisch ist, ist die Übergabe eines pointerss in Ihrem Anwendungsfall besser lesbar, da dadurch die Tatsache “angekündigt” wird, dass der Wert von der function geändert wird.

pointers Vs. Referenzen

Referenzen sind weniger mächtig als pointers:

1) Sobald eine Referenz erstellt wurde, kann sie später nicht mehr auf ein anderes Objekt verweisen; Es kann nicht erneut festgelegt werden. Dies wird oft mit pointersn gemacht.

2) Referenzen können nicht NULL sein. pointers werden oft als NULL gesetzt, um anzuzeigen, dass sie nicht auf eine gültige Sache zeigen.

3) Eine Referenz muss bei der Deklaration initialisiert werden. Es gibt keine solche Beschränkung mit pointersn

Aufgrund der obigen Einschränkungen können Verweise in C ++ nicht zum Implementieren von Datenstrukturen wie Linked List , Tree usw. verwendet werden. In Java haben Verweise keine obigen Einschränkungen und können zum Implementieren aller Datenstrukturen verwendet werden. Referenzen, die in Java leistungsfähiger sind, sind der Hauptgrund, warum Java keine pointers benötigt.

Referenzen sind sicherer und einfacher zu verwenden:

1) Sicherer: Da Referenzen initialisiert werden müssen, ist es unwahrscheinlich, dass Wild-Referenzen wie Wild-Pointer existieren. Es ist immer noch möglich, Referenzen zu haben, die sich nicht auf einen gültigen Standort beziehen

2) Einfacher zu verwenden: Verweise benötigen keinen Dereferenzierungsoperator, um auf den Wert zuzugreifen. Sie können wie normale Variablen verwendet werden. Der Operator ‘&’ wird nur zum Zeitpunkt der Deklaration benötigt. Auf Elemente einer Objektreferenz kann auch mit dem Punktoperator (‘.’) Zugegriffen werden, im Gegensatz zu pointersn, bei denen der Pfeiloperator (->) benötigt wird, um auf Mitglieder zuzugreifen.

Zusammen mit den oben genannten Gründen gibt es wenige Stellen wie das Copy-Konstruktorargument, bei dem der pointers nicht verwendet werden kann. Referenz muss verwendet werden, übergeben Sie das Argument im Kopierkonstruktor. In ähnlicher Weise müssen Referenzen verwendet werden, um einige Operatoren wie ++ zu überladen .

Wenn Sie einen Parameter haben, bei dem Sie möglicherweise angeben müssen, dass ein Wert fehlt, ist es üblich, den Parameter zu einem pointerswert zu machen und NULL zu übergeben.

Eine bessere Lösung in den meisten Fällen (aus Sicherheitsgründen) ist boost :: optional . Dadurch können Sie optionale Werte als Referenz und auch als Rückgabewert übergeben.

 // Sample method using optional as input parameter void PrintOptional(const boost::optional& optional_str) { if (optional_str) { cout < < *optional_str << std::endl; } else { cout << "(no string)" << std::endl; } } // Sample method using optional as return value boost::optional ReturnOptional(bool return_nothing) { if (return_nothing) { return boost::optional(); } return boost::optional(42); } 

Verwenden Sie einen Verweis, wenn Sie können, verwenden Sie einen pointers, wenn Sie müssen. Aus C ++ – FAQ: “Wann sollte ich Verweise verwenden und wann sollte ich pointers verwenden?”

Eine Referenz ist ein impliziter pointers. Grundsätzlich können Sie den Wert ändern, auf den die Referenzpunkte verweisen, aber Sie können die Referenz nicht ändern, um auf etwas anderes zu zeigen. Also meine 2 Cent ist, dass, wenn Sie nur den Wert eines Parameters ändern wollen, übergeben Sie es als Referenz, aber wenn Sie den Parameter ändern müssen, um auf ein anderes Objekt zu zeigen, übergeben Sie es mit einem pointers.

Betrachte C # ‘s out-Schlüsselwort. Der Compiler benötigt den Aufrufer einer Methode, um das out-Schlüsselwort auf alle ausgehenden Argumente anzuwenden, obwohl es bereits weiß, ob sie es sind. Dies soll die Lesbarkeit verbessern. Obwohl ich bei modernen IDEs der Meinung bin, dass dies eine Aufgabe für Syntax (oder semantische) Hervorhebung ist.

Pass by const reference, es sei denn, es gibt einen Grund, den Inhalt, den du übergibst, zu ändern / zu behalten.

Dies wird in den meisten Fällen die effizienteste Methode sein.

Stellen Sie sicher, dass Sie const für jeden Parameter verwenden, den Sie nicht ändern möchten, da dies nicht nur davor schützt, etwas Dummes in der function zu tun, sondern anderen Benutzern einen guten Hinweis darauf gibt, was die function mit den übergebenen Werten macht. Dazu gehört, einen pointers const zu machen, wenn Sie nur das ändern wollen, auf das gezeigt wird …

pointers:

  • Kann nullptr (oder NULL ) zugewiesen werden.
  • An der Aufrufstelle müssen Sie & verwenden, wenn Ihr Typ kein pointers selbst ist, wodurch Sie explizit Ihr Objekt verändern.
  • pointers können zurückprallen.

Verweise:

  • Kann nicht Null sein.
  • Einmal gebunden, kann sich nicht ändern.
  • Anrufer müssen nicht explizit & verwenden. Dies wird manchmal als schlecht angesehen, da Sie zur Implementierung der function gehen müssen, um zu sehen, ob Ihr Parameter geändert wurde.

pointers

  • Ein pointers ist eine Variable, die eine Speicheradresse enthält.
  • Eine pointersdeklaration besteht aus einem Basistyp, einem * und dem Variablennamen.
  • Ein pointers kann auf eine beliebige Anzahl von Variablen in der Lebensdauer zeigen
  • Ein pointers, der gerade nicht auf einen gültigen Speicherplatz zeigt, erhält den Wert null (Which ist Null)

     BaseType* ptrBaseType; BaseType objBaseType; ptrBaseType = &objBaseType; 
  • Der & 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 pointers zeigt.

      int nVar = 7; int* ptrVar = &nVar; int nVar2 = *ptrVar; 

Referenz

  • Ein Verweis (&) ist wie ein Alias ​​für eine vorhandene Variable.

  • Ein Verweis (&) ist wie ein konstanter pointers, der automatisch dereferenziert wird.

  • Es wird normalerweise für functionsargumentlisten und functionsrückgabewerte verwendet.

  • Ein Verweis muss beim Erstellen initialisiert werden.

  • Sobald eine Referenz für ein Objekt initialisiert wurde, kann sie nicht geändert werden, um auf ein anderes Objekt zu verweisen.

  • Sie können keine NULL-Referenzen haben.

  • Ein const-Verweis kann sich auf einen const int beziehen. Es wird mit einer temporären Variablen mit dem Wert const gemacht

     int i = 3; //integer declaration int * pi = &i; //pi points to the integer i int& ri = i; //ri is refers to integer i – creation of reference and initialization 

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben