Frage

Was sind die Vorteile der durch den Zeiger über Gang durch Verweis in C ++ vorbei?

In letzter Zeit habe ich eine Reihe von Beispielen gesehen, dass anstelle des Führens durch Bezugnahme durch Zeiger Funktionsargumente wählte vorbei. Gibt es Vorteile, dies zu tun?

Beispiel:

func(SPRITE *x);

mit einem Aufruf von

func(&mySprite);

vs.

func(SPRITE &x);

mit einem Aufruf von

func(mySprite);
War es hilfreich?

Lösung

Ein Zeiger kann einen NULL-Parameter erhalten, ein Referenzparameter nicht. Wenn es jemals eine Chance, dass man sich wünschen kann „kein Objekt“ passieren, dann einen Zeiger anstelle eines Verweises.

Auch durch die Zeiger vorbei können Sie explizit an der Aufrufstelle, um zu sehen, ob das Objekt als Wert oder als Referenz übergeben wird:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

Andere Tipps

Vorbei Zeiger

  • Anrufer hat die Adresse zu übernehmen -> nicht transparent
  • A 0 Wert kann bedeuten nothing zur Verfügung gestellt werden. Dies kann verwendet werden optionale Argumente zu liefern.

Pass durch Verweis

  • Caller geht nur um das Objekt -> transparent. Muss für Betreiber Überlastung verwendet werden, da Zeigertypen für Überlastung nicht möglich ist (Zeiger-Typen sind builtin). So können Sie nicht tun string s = &str1 + &str2; Zeiger verwendet werden.
  • Keine 0 Werte möglich -> Aufgerufene Funktion muss nicht für sie überprüfen
  • Verweis auf const auch Provisorien akzeptiert. void f(const T& t); ... f(T(a, b, c));, können Zeiger nicht so verwendet werden, da Sie nicht die Adresse eines temporären nehmen
  • Last but not least, Referenzen sind einfacher zu bedienen. -> weniger Chancen für Fehler

Alle Holub des "Enough Rope zu schießen selbst in dem Fuß" ist die folgenden zwei Regeln:

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

Er listet mehrere Gründe, warum Referenzen wurden in C ++ hinzugefügt:

  • Sie sind notwendig Kopierkonstruktoren
  • zu definieren,
  • Sie sind notwendig für die Betreiber Überlastungen
  • const Referenzen können Sie Pass-by-Wert Semantik haben, während eine Kopie
  • Vermeidung

Sein Hauptpunkt ist, dass Referenzen nicht als ‚Output‘ Parameter beim Aufruf-Website verwendet werden, da gibt es keinen Hinweis darauf, ob der Parameter einen Verweis oder ein Wertparameter. So seine Herrschaft ist nur const Referenzen als Argumente verwendet werden.

Ich persönlich denke, das ist eine gute Faustregel, wie sie es deutlich macht, wenn ein Parameter ein Ausgabeparameter ist oder nicht. Doch während ich persönlich mit diesem in der Regel zustimmen, ich lasse mich von der Meinung anderer in meinem Team schwankte werden, wenn sie für die Ausgabeparameter als Referenzen argumentieren (einige Entwickler wie sie enorm).

Ich mag die Argumentation durch einen Artikel von "cplusplus.com:"

  
      
  1. Wertübergabe, wenn die Funktion nicht will, um die Parameter zu ändern, und der Wert ist leicht (Ints zu kopieren, Doppel-, char, bool, etc ... einfache Typen. Std :: string, std :: Vektor, und alle anderen STL-Container sind nicht einfache Typen.)

  2.   
  3. Pass von const Zeigern, wenn der Wert teuer zu kopieren und die Funktion will keine gültiger, Erwartungswert der Wert zeigte auf AND NULL ändern, dass die Funktion behandelt.

  4.   
  5. Sie passieren nicht konstante Zeiger, wenn der Wert teuer zu kopieren und die Funktion will der Wert ändern wies auf UND NULL ist ein gültiger, Erwartungswert, dass die Funktion behandelt.

  6.   
  7. Führen durch konstante Referenz, wenn der Wert teuer zu kopieren und die Funktion will nicht den Wert bezeichnet ändern und NULL würde ein gültiger Wert nicht, wenn ein Zeiger verwendet wurde, statt.

  8.   
  9. Pass von nicht-cont Referenz, wenn der Wert teuer zu kopieren und die Funktion will den Wert bezeichnet und NULL ändern, würde einen gültigen Wert nicht, wenn ein Zeiger verwendet wurde, statt.

  10.   
  11. Wenn Template-Funktionen zu schreiben, gibt es keine klare Antwort, weil es ein paar Nachteile zu berücksichtigen sind, die über den Rahmen dieser Diskussion, aber es genügt zu sagen, dass die meisten Template-Funktionen ihre Parameter übernehmen durch Wert oder (const) Referenz, jedoch wegen Iterator Syntax ist ähnlich der von Zeigern (Sternchen auf „dereferenzieren“), jede Template-Funktion, die seit der NULL-Iteratoren als Argumente wird auch standardmäßig annehmen Zeiger als auch (und nicht, für NULL erwartet Iterator-Konzept hat eine andere Syntax).

  12.   
     

http://www.cplusplus.com/articles/z6vU7k9E/

Was ich daraus nehmen ist, dass der Hauptunterschied zwischen der Auswahl eines Zeiger oder Referenzparameter zu verwenden ist, wenn NULL ein akzeptabler Wert ist. Das ist es.

Ob der Wert Eingang, Ausgang, veränderbar usw. in der Dokumentation / Bemerkungen über die Funktion sein sollte, nachdem alle.

Clarifications die vorhergehenden Beiträge:


Referenzen sind nicht eine Garantie für einen Nicht-Null-Zeiger zu bekommen. (Obwohl wir behandeln sie oft als solche.)

Während horrifically schlechter Code, wie in Sie die hinter dem Holzschuppen schlecht Code, die folgenden kompilieren und ausführen: (. Mindestens unter meinem Compiler)

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};

Das eigentliche Problem, das ich mit Referenzen habe mit anderen Programmierern liegt, von nun an bezeichnet IDIOTS , der im Konstruktor ausplanen im destructor zuteilen, und nicht eine Kopie Konstruktor oder Betreiber liefern = ().

Auf einmal gibt es einen großen Unterschied zwischen foo (BAR bar) und foo (BAR & bar) . (Automatic bitweise Kopiervorgang wird aufgerufen. Ausplanung in destructor zweimal aufgerufen wird.)

Zum Glück moderne Compiler wird diese Doppel Aufhebung der Zuordnung der gleichen Zeiger holen. Vor 15 Jahren haben sie nicht. (Unter gcc / g ++, verwenden Sie setenv MALLOC_CHECK_ 0 die alten Wege zu überdenken.) Resultierende unter UNIX Dezember, in demselben Speicher zu zwei unterschiedlichen Objekten zugeordnet werden. Viel Spaß Debugging es ...


Mehr praktisch:

  • Referenzen verbergen, dass Sie Daten woanders gespeichert ändern.
  • Es ist einfach eine Referenz mit einem kopierten Objekt zu verwechseln.
  • Pointers macht es auf der Hand!

Nicht wirklich. Intern vorbei Referenz wird im wesentlichen durch das Bestehen der Adresse des referenzierten Objekts durchgeführt wird. Also, es gibt wirklich keine Effizienzgewinne, indem einen Zeiger werden mußte.

Passing durch Bezugnahme einen Vorteil hat, jedoch. Sie garantiert eine Instanz unabhängig von Objekt / Typ haben, die in übergeben wird. Wenn Sie in einem Zeiger übergeben, dann sind Sie das Risiko einer Aufnahme eines NULL-Zeiger laufen. Durch die Verwendung von Pass-by-reference, Sie eine implizite drängen NULL-Check eine Ebene höher an den Aufrufer Ihrer Funktion.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top