Zeiger vs. Referenz

Lesezeit: 9 Minuten

Zeiger vs Referenz
Jack Reza

Was wäre eine bessere Vorgehensweise, 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 dem anderen vorzuziehen?

  • Referenzen sind natürlich wertvoll, aber ich komme aus C, wo Zeiger überall sind. Man muss zuerst mit Zeigern vertraut sein, um den Wert von Referenzen zu verstehen.

    – Jay D

    8. Mai 2012 um 19:43 Uhr

  • Wie passt das zu einem Ziel wie referentielle Transparenz aus der funktionalen Programmierung? Was ist, wenn Sie möchten, dass Funktionen immer neue Objekte zurückgeben und den Status niemals intern ändern, insbesondere nicht von Variablen, die an die Funktion übergeben werden? Gibt es eine Möglichkeit, dieses Konzept immer noch mit Zeigern und Referenzen in einer Sprache wie C++ zu verwenden. (Beachten Sie, ich gehe davon aus, dass jemand bereits das Ziel der referenziellen Transparenz hat. Ich bin nicht daran interessiert, darüber zu sprechen, ob es ein gutes Ziel ist oder nicht.)

    – Ely

    30. September 2013 um 17:31 Uhr

  • Referenzen bevorzugen. Benutzerhinweise, wenn Sie keine Wahl haben.

    – Ferruccio

    5. Juli 2014 um 13:14 Uhr

1646979012 664 Zeiger vs Referenz
Nils Pipenbrink

Meine Faustregel lautet:

Verwenden Sie Zeiger, wenn Sie mit ihnen Zeigerarithmetik durchführen wollen (zB die Zeigeradresse erhöhen, um ein Array zu durchlaufen) oder wenn Sie jemals einen NULL-Zeiger übergeben müssen.

Verwenden Sie ansonsten Referenzen.

  • Ausgezeichneter Punkt bezüglich eines Zeigers, der NULL ist. Wenn Sie einen Zeigerparameter haben, müssen Sie entweder explizit prüfen, dass er nicht NULL ist, oder alle Verwendungen der Funktion durchsuchen, um sicherzustellen, dass er niemals NULL ist. Bei Referenzen entfällt dieser Aufwand.

    – Richard Corden

    22. September 2008 um 11:10 Uhr

  • Erklären Sie, was Sie unter Arithmetik verstehen. Ein neuer Benutzer versteht möglicherweise nicht, dass Sie anpassen möchten, worauf der Zeiger zeigt.

    – Martin York

    22. September 2008 um 16:30 Uhr

  • Martin, mit Arithmetik meine ich, dass Sie einen Zeiger auf eine Struktur übergeben, aber wissen, dass es sich nicht um eine einfache Struktur handelt, sondern um ein Array davon. In diesem Fall können Sie es entweder mit indizieren [] oder rechnen Sie mit ++/– auf dem Zeiger. Das ist der Unterschied in Kürze.

    – Nils Pipenbrinck

    25. November 2008 um 20:35 Uhr

  • Martin, das geht nur mit Zeigern direkt. Nicht mit Referenzen. Sicher, Sie können einen Zeiger auf eine Referenz nehmen und in der Praxis dasselbe tun, aber wenn Sie dies tun, enden Sie mit sehr schmutzigem Code.

    – Nils Pipenbrinck

    25. November 2008 um 20:38 Uhr

  • Was ist mit Polymorphismus (zB Base* b = new Derived())? Dies scheint ein Fall zu sein, der ohne Hinweise nicht behandelt werden kann.

    – Chris Redford

    7. März 2013 um 19:25 Uhr

Zeiger vs Referenz
Johann Gell

Ich denke wirklich, dass Sie davon profitieren werden, wenn Sie die folgenden Codierungsrichtlinien für Funktionsaufrufe festlegen:

  1. Wie an allen anderen Orten immer sein const-Korrekt.

    • Hinweis: Das bedeutet unter anderem, dass nur out-Werte (siehe Punkt 3) und als Wert übergebene Werte (siehe Punkt 4) fehlen können const Bezeichner.
  2. Übergeben Sie einen Wert nur per Zeiger, wenn der Wert 0/NULL im aktuellen Kontext eine gültige Eingabe ist.

    • Begründung 1: Als ein AnruferSie sehen das, was auch immer Sie passieren muss sein in einem brauchbaren Zustand.

    • Begründung 2: Als namensdu weißt, was auch immer reinkommt ist in einem brauchbaren Zustand. Daher muss für diesen Wert keine NULL-Prüfung oder Fehlerbehandlung durchgeführt werden.

    • Begründung 3: Begründung 1 und 2 werden sein Compiler erzwungen. Fangen Sie Fehler immer zur Kompilierzeit ab, wenn Sie können.

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

    • Begründung: Wir wollen Punkt 2 nicht brechen …
  4. Wählen Sie “Pass by Value” gegenüber “Pass by Const Reference” nur dann, wenn der Wert ein POD (Plain Old Datastructure) oder klein genug (speichermäßig) oder auf andere Weise billig genug (zeitlich) zum Kopieren ist.

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

  • Es fehlt die Richtlinie, wenn: … “wann const & verwendet werden soll” … Die Richtlinie 2 sollte geschrieben werden “für [in] Werte, Zeiger nur übergeben, wenn NULL gültig ist. Verwenden Sie andernfalls const reference (oder für “kleine” Objekte copy) oder reference, falls es sich um eine handelt [out] Wert. Ich beobachte diesen Beitrag, um möglicherweise +1 hinzuzufügen.

    – Paercebal

    22. September 2008 um 11:54 Uhr

  • Punkt 1 deckt den von Ihnen beschriebenen Fall ab.

    – Johann Gerell

    22. September 2008 um 13:14 Uhr

  • Es ist ein bisschen schwierig, einen Out-Parameter als Referenz zu übergeben, wenn er nicht standardmäßig konstruierbar ist. Das kommt in meinem Code ziemlich häufig vor – der einzige Grund dafür, dass eine Funktion dieses Out-Objekt erstellt, ist, dass es nicht trivial ist.

    – MSalter

    22. September 2008 um 15:02 Uhr

  • @MSalters: Wenn Sie den Speicher innerhalb der Funktion zuweisen (was Sie meiner Meinung nach meinen), warum geben Sie dann nicht einfach einen Zeiger auf den zugewiesenen Speicher zurück?

    – Kleist

    16. Februar 2011 um 9:27 Uhr

  • @Kleist: Im Namen von @MSalters gibt es viele mögliche Gründe. Einer davon ist, dass Sie möglicherweise bereits Speicher zugewiesen haben, um ihn zu füllen, wie bei einer voreingestellten Größe std::vector<>.

    – Johann Gerell

    16. Februar 2011 um 10:28 Uhr

1646979013 779 Zeiger vs Referenz
Aaron N. Tubbs

Das ist letztlich subjektiv. Die bisherige Diskussion ist nützlich, aber ich glaube nicht, dass es darauf eine richtige oder entscheidende Antwort gibt. Vieles hängt von den Stilrichtlinien und Ihren aktuellen Bedürfnissen ab.

Während es bei einem Zeiger einige unterschiedliche Fähigkeiten gibt (ob etwas NULL sein kann oder nicht), besteht der größte praktische Unterschied für einen Ausgabeparameter in der reinen Syntax. Googles C++ Style Guide (https://google.github.io/styleguide/cppguide.html#Reference_Arguments) verlangt beispielsweise nur Zeiger für Ausgabeparameter und erlaubt nur Verweise, die konstant sind. Der Grund liegt in der Lesbarkeit: Etwas mit Wertesyntax sollte keine semantische Zeigerbedeutung 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.

  • Was bedeutet es, dass Referenzen eine Wertsyntax, aber eine semantische Zeigerbedeutung haben?

    – Eric Andrew Lewis

    16. August 2015 um 13:43 Uhr

  • Es sieht so aus, als würden Sie eine Kopie übergeben, da der Teil “Pass by Reference” nur aus der Funktionsdefinition (Wertsyntax) ersichtlich ist, aber Sie kopieren nicht den Wert, den Sie übergeben, Sie übergeben im Wesentlichen einen Zeiger unter der Haube, was dies ermöglicht die Funktion, um Ihren Wert zu ändern.

    – phant0m

    19. Mai 2016 um 10:35 Uhr

  • Man sollte nicht vergessen, dass der Google C++ Styleguide sehr verabscheut wird.

    – Deduplizierer

    20. Dezember 2018 um 0:54 Uhr

Zeiger

  • Ein Zeiger ist eine Variable, die eine Speicheradresse enthält.
  • Eine Zeigerdeklaration besteht aus einem Basistyp, einem * und dem Variablennamen.
  • Ein Zeiger kann während der Lebensdauer auf eine beliebige Anzahl von Variablen zeigen
  • Ein Zeiger, der derzeit nicht auf einen gültigen Speicherplatz zeigt, erhält den Wert null (was null ist).

    BaseType* ptrBaseType;
    BaseType objBaseType;
    ptrBaseType = &objBaseType;
    
  • Das & ist ein unärer Operator, der die Speicheradresse seines Operanden zurückgibt.

  • Dereferenzierungsoperator

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

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 initialisiert werden, wenn sie erstellt wird.

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

  • Sie können keine NULL-Referenzen haben.

    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
    

Eine const-Referenz kann auf ein const int verweisen.  Dies geschieht mit einer temporären Variablen mit dem Wert der Konstante

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

  • Sie sollten einen Zeiger übergeben, wenn Sie den Wert der Variablen ändern möchten. Obwohl das Übergeben einer Referenz oder eines Zeigers technisch gesehen dasselbe ist, ist das Übergeben eines Zeigers in Ihrem Anwendungsfall besser lesbar, da er die Tatsache „ankündigt“, dass der Wert durch die Funktion geändert wird.

    Wenn Sie den Richtlinien von Johann Gerell folgen, kündigt eine nicht konstante Referenz auch eine veränderbare Variable an, sodass der Zeiger hier diesen Vorteil nicht hat.

    – Alexander Kondratsky

  • 19. Juli 2011 um 13:39 Uhr @AlexanderKondratskiy: Sie verfehlen den Punkt … Sie können nicht sofort sehen am Aufrufort const ob die aufgerufene Funktion einen Parameter als akzeptiertconst oder nicht- &x Referenz, aber Sie können sehen, ob der Parameter ala übergeben wurde xvs. const , und verwenden Sie diese Konvention, um zu codieren, ob der Parameter geändert werden kann. (Das heißt, es gibt Zeiten, in denen Sie eine bestehen möchten

    Zeiger, also ist die Konvention nur ein Hinweis. Es ist weniger gefährlich zu vermuten, dass etwas geändert werden könnte, wenn es nicht sein wird, als zu glauben, dass es nicht sein wird, wenn es sein wird ….)

    – Toni Delroy

1646979014 544 Zeiger vs Referenz
17. Juni 2015 um 7:29 Uhr

Kiley Hykawy

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 ist in den meisten Fällen (aus Sicherheitssicht) die Verwendungsteigern::optional

// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& 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<int> ReturnOptional(bool return_nothing)
{
    if (return_nothing)
    {
       return boost::optional<int>();
    }

    return boost::optional<int>(42);
}

  • . Dadurch können Sie optionale Werte als Referenz und auch als Rückgabewert übergeben.

    Wenn Sie den Richtlinien von Johann Gerell folgen, kündigt eine nicht konstante Referenz auch eine veränderbare Variable an, sodass der Zeiger hier diesen Vorteil nicht hat.

    – Alexander Kondratsky

  • 19. Juli 2011 um 13:39 Uhr @AlexanderKondratskiy: Sie verfehlen den Punkt … Sie können nicht sofort sehen am Aufrufort const ob die aufgerufene Funktion einen Parameter als akzeptiertconst oder nicht- &x Referenz, aber Sie können sehen, ob der Parameter ala übergeben wurde xvs. const , und verwenden Sie diese Konvention, um zu codieren, ob der Parameter geändert werden kann. (Das heißt, es gibt Zeiten, in denen Sie eine bestehen möchten

    Zeiger, also ist die Konvention nur ein Hinweis. Es ist weniger gefährlich zu vermuten, dass etwas geändert werden könnte, wenn es nicht sein wird, als zu glauben, dass es nicht sein wird, wenn es sein wird ….)

    – Toni Delroy

1646979015 215 Zeiger vs Referenz
17. Juni 2015 um 7:29 Uhr

seaotterd Verwenden Sie eine Referenz, wenn Sie können, verwenden Sie einen Zeiger, wenn Sie müssen. Von

990060cookie-checkZeiger vs. Referenz

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy