Ich habe kürzlich eine Funktion gesehen, die folgendermaßen deklariert wird:
%Vor% Ich kenne den Unterschied zwischen type* param
und type& param
bereits. Wie unterscheidet sich das obige von ihnen? Und wann sollte man das benutzen? Ist es ratsam, dies zu tun?
Das obige wird in der Lage sein, nicht nur das spitze Objekt, sondern auch den Zeiger selbst zu modifizieren. Betrachten Sie als Beispiel den folgenden Code:
%Vor% Am Ende der Ausführung hat x
den Wert 1
und y
ist 0
(wie Sie kann sehen ).
Beachten Sie, dass ich für das Beispiel 0
als Nullzeiger verwendet habe, aber wenn Sie C ++ 11 verwenden, dann sollte wahrscheinlich stattdessen nullptr
verwenden (ohne überladene operaror<<
für std::ostream
).
Dieses Konzept kann möglicherweise durch einen Blick auf den folgenden Code assimiliert werden:
%Vor%oder
%Vor% In diesen Beispielen ist x
eine Referenz auf einen Typ ( ptr<int>
und dann std::unique_ptr<int>
), was zufällig ein Zeiger / Klasse mit Pointer-Semantik ( operator*
und operator->
) ist.
Ein möglicherweise interessanter Exkurs kann an der Position eines const
-Qualifikators im Zeiger vorgenommen werden. Betrachten Sie diese zwei Instanzen:
void func(const int*& ptr)
void func(int*const& ptr)
Ihre Bedeutungen sind:
Und nach der obigen Analogie mit ptr
wären sie:
ptr<const int>&
ptr<int> const&
Daher kann der erste Befehl *ptr = 1
nicht im Körper der Funktion ausführen (weil int
konstant ist), aber wird ptr = 0
gerne ausführen.
Die zweite verhält sich umgekehrt, erlaubt *ptr = 1
(weil das angegebene int nicht konstant ist), während ptr = 0
nicht erlaubt ist (weil der Zeiger konstant ist).
Natürlich im Fall von:
%Vor% was in der ptr
Analogie wäre ptr<const int> const&
, beide wären nicht erlaubt.
Und wann soll ich das benutzen? Ist es ratsam, dies zu tun?
Wie jedes Feature finden Sie es nützlich, wenn Sie es brauchen. Aber als allgemeine Idee haben einige Leute den Zeiger nach dem Freigeben einer dynamisch zugewiesenen Ressource zurückgesetzt (ich empfehle das nicht, siehe unten).
Nehmen wir das Beispiel:
%Vor% Am Ende der Ausführung wird x
korrekt freigegeben und der Zeiger automatisch auf nullptr
gesetzt. (Nullzeiger) Dies wurde getan, um hässliche Segmentierungsfehler oder "Zeiger freigegeben wurde nicht zugeordnet" -Fehlermeldungen, die durch ein fehlendes ptr = nullptr
verursacht wurden, zu vermeiden.
Aber mit C ++ 11 und C ++ 14 wird sehr wenig auf Zeiger und noch weniger auf Zeiger zurückgegriffen. Die meisten der Dinge, für die Zeiger verwendet werden, werden nicht durch andere Standardkonstrukte ersetzt (siehe std::optional
, < a href="http://en.cppreference.com/w/cpp/memory/unique_ptr"> std::unique_ptr
, std::shared_ptr
oder std::reference_wrapper
zum Beispiel).
Vergleichen wir alle drei Optionen:
void func(type* param); // 'param' is a 'type*' variable
void func(type& param); // 'param' is a reference to a 'type' variable
void func(type*& param); // 'param' is a reference to a 'type*' variable
Natürlich, wenn Sie *param = ...
verwenden, wird den Inhalt des Speichers, auf den param
zeigt, beeinflussen. Und Sie können zum Beispiel auch param[5] = ...
ausführen und andere Bereiche innerhalb dieses Speicherplatzes beeinflussen.
Hier ändern Sie nur die referenzierte Variable selbst . Es ist also sicherer, die Funktion als void func(type* param)
zu deklarieren und dann die Adresse von type param
zu übergeben, indem Sie func(¶m)
aufrufen.
Dies ist ähnlich wie die Funktion void func(type** param)
zu deklarieren und dann die Adresse von type* param
durch Aufruf von func(¶m)
zu übergeben, aber wiederum ist es aus dem gleichen Grund sicherer.
Tags und Links c++ parameter-passing