Ich habe oft Schwierigkeiten, die Vorteile von Zeigern zu erkennen (außer bei der Programmierung auf niedriger Ebene).
Warum char * anstelle eines Strings oder char [] verwenden oder welche Vorteile Zeigerarithmetik bringt.
Was sind die Profis und Anwendungsfälle von Zeigern?
Antworten:
Zeiger sind für den dynamischen Speicherort, viele Datenstrukturen und den effizienten Umgang mit großen Datenmengen erforderlich. Ohne Zeiger müssten Sie alle Programmdaten global oder in Funktionen oder dergleichen zuordnen, und Sie hätten keinen Rückgriff, wenn die Datenmenge über das hinausgehen würde, was Sie ursprünglich zugelassen hatten. Ich zögere, hier Absolutes zu verwenden, aber soweit ich weiß, haben alle modernen Computersprachen Zeiger in irgendeiner Form.
In den meisten Sprachen, die Zeiger verwenden, gibt es bestimmte Arten von Referenzen, die Zeiger sind, und möglicherweise bestimmte Arten von Referenzen, die dies nicht sind, und es gibt keinen weiteren Unterschied in der Notation. Eine Lisp-
cons
Zelle ist ein Zeigerpaar, obwohl afixnum
kein Zeiger ist. In Java ist die für die Instanz einer Klasse verwendete Variable ein Zeiger, ein Zeiger jedochint
nicht. Die Sprachsyntax spiegelt dies nicht wider.C ist insofern ungewöhnlich, als Zeiger optional und explizit sind und eine explizite Zeigerarithmetik zulassen. Es ist durchaus möglich , zu schreiben
struct foo bar; struct foo * baz;
, und wenn Sie Speicher zugewiesen haben fürbaz
Sie beide zu verwendenbar
undbaz
darzustellenstruct foo
s. Da Zeiger optional sind, ist es nützlich, Unterschiede in der Notation zu haben. (In C ++ ist es wichtig, dass intelligente Zeiger, wie angegebenboost::shared_ptr<foo> bar;
,bar.reset()
eine Bedeutung haben undbar->reset()
wahrscheinlich eine ganz andere haben.)(Tatsächlich wurden explizite Zeiger häufig in anderen Sprachen verwendet, als C ursprünglich entwickelt wurde, wie beispielsweise
^
in Pascal. C ist eine ältere Sprache als die meisten heute gebräuchlichen und zeigt dies.)Eines der Entwurfsziele von C war das Schreiben von Unix. Daher musste der Speicherort detailliert behandelt werden. (C gehört tatsächlich zu einer Familie von Systemimplementierungssprachen, die bei der Entwicklung häufig verwendet wurden. Ein weiteres Beispiel ist Cybol für Control Data-Computer. C ist ein großer Erfolg.) Daher ist es möglich, C-Zeiger direkt zu manipulieren. Speicheradressen zuweisen und neue berechnen. Dies führte auch zu einigen Entwurfsentscheidungen in C. C-Arrays basieren stark auf Zeigerarithmetik, und tatsächlich zerfällt ein Array in sehr vielen Situationen in einen Zeiger. Die Übergabe von Variablen an C-Funktionen als Referenz erfolgt per Zeiger. Es bestand kein starker Bedarf an Arrays und Übergabe von Variablen als Referenz in der Form, die andere zeitgenössische Sprachen hatten, so dass C diese nicht bekam.
Die Antwort lautet also, dass Sie heutzutage in den meisten Sprachen ständig Zeiger verwenden, ohne daran erinnert zu werden. In C und in geringerem Maße in C ++ verwenden Sie Zeiger entweder, um Dinge auf niedriger Ebene auszuführen oder um Dinge auf höherer Ebene auszuführen, für die es keine spezielle Notation gibt.
quelle
Komplexe Datenstrukturen. Sie können so etwas wie eine verknüpfte Liste oder einen Binärbaum nicht ohne Zeiger erstellen.
Es gibt keine "Vor- und Nachteile" von Zeigern. Sie sind nur ein Werkzeug wie ein Hammer.
quelle
Referenzen in C ++, Java und anderen Sprachen sind nur "sichere Zeiger". Und diese Referenzen werden in Java häufig verwendet.
quelle
NULL
und nach ihrer Erstellung nicht mehr geändert werden.So ziemlich jedes Computerprogramm muss Werte im Speicher überprüfen und ändern (bekannt als Spähen und Stöbern für diejenigen von uns, die alt genug sind). Sie müssen steuern, wo sich diese Werte im Speicher befinden, damit das Ergebnis vorhersehbar ist (und in bestimmten Fällen ist die Reihenfolge wichtig: Das Laden von ausführbarem Code ist ein Beispiel). Daher benötigen Sie einen Datentyp, der einen Speicherort im Speicher darstellt. Auch wenn Ihre Programmierumgebung dies unter einer Abstraktion verbirgt, ist es immer noch da.
quelle
char*
ist ein mieses Beispiel für Zeiger. Sie sind wahrscheinlich besser dran alsstd::string
(oder ein besserer Typ, der Ihre Unicode / Ansi / Multibyte-Spezialität behandelt) alschar*
. Für fast jeden anderes Beispiel von Zeigern (Employee*
,PurchaseOrder*
, ...), gibt es jedoch viele Vorteile:In der Tat sind Zeiger so wichtig, dass die meisten Sprachen, die sie scheinbar nicht haben, tatsächlich nur sie haben. Referenztypen in C # und Java sind im Wesentlichen Zeiger, die als feste Objekte getarnt sind.
Jetzt ist die Zeigermanipulation (
p++
auf einem Zeiger oderp += delta
) eine ganz andere Geschichte. Einige Leute halten es für gefährlich, andere für großartig. Aber das ist noch weiter von Ihrer Frage entfernt.quelle
Zeiger können schneller sein und weniger Overhead verursachen, sowohl in Datenstrukturen als auch bei der Reduzierung des Programmausführungs-Footprints. (Bitte beachten Sie das Wort "kann".)
Im Allgemeinen lautet die Regel: Wenn Sie eine Ressource zugewiesen haben, indem Sie entweder Ihre eigene Zuweisung vorgenommen haben oder etwas in Ihrem Namen ausführen lassen, ist es Ihre Aufgabe, sie freizugeben, wenn Sie fertig sind.
Die Last der oben genannten Aufgaben besteht darin, die Verantwortung wieder auf den Entwickler zu übertragen, anstatt sie von der Laufzeit ausführen zu lassen. Dies hat einige weitere Vorteile, da Dinge länger leben oder Grenzen überschreiten oder zu günstigeren Zeiten entsorgt werden können oder nicht das Gewicht eines Müllsammlers tragen müssen.
In exotischen Fällen, die normalerweise Ausnahmen und Umfang beinhalten, gibt es einige Randfälle, bei denen man etwas vorsichtiger sein muss, wenn der Code, der bereinigt wird, vermieden wird. Realistisch gesehen können diese Fälle umgestaltet werden. Wir haben viele Jahrzehnte ohne verwalteten Code gelebt.
Was Zeiger oft "schwer" macht, ist einfach nicht zu verstehen, was auf Hardwareebene vor sich geht. Es ist nichts weiter als Indirektion.
Zeiger bieten Ihnen viel mehr Zugriff, und dies kann sehr hilfreich, clever oder notwendig sein. Sie können überall hin zeigen und es so ziemlich wie alles behandeln. Wenn Sie Ihre gottähnlichen Kräfte zum Guten einsetzen, ist das sehr, sehr gut.
Die Gegenseite ist normalerweise eine Verschwendung, wenn Sie vergessen, etwas freizugeben, oder indem Sie es mehrmals freigeben oder auf etwas verweisen, nachdem es freigegeben wurde, oder wenn Sie etwas verweisen, wenn Sie nicht auf etwas zeigen. Diese Dinge führen oft zu spektakulären Abstürzen, und um ehrlich zu sein, deuten sie normalerweise darauf hin, dass Sie ein logisches Problem haben, anstatt dass Zeiger zerbrechlich sind.
Wenn Sie ein solider Entwickler sind, sollte die Verwendung von Zeigern nicht problematischer sein als jede andere Datenstruktur. Auch hier ist es keine Raketenwissenschaft, und die Leute haben es jahrzehntelang getan, ohne ein Auge zu blinzeln. Es wird heutzutage nur weniger gründlich gelehrt.
Abgesehen davon macht die Konveinenz und die exoitischen Fälle, die eine gute Speicherbereinigung bietet, die Arbeit in einer verwalteten Umgebung umso angenehmer, es sei denn, Sie benötigen Zeiger. Es ist großartig, etwas Speicher abrufen, verwenden und aufgeben zu können, da man weiß, dass es zu einem späteren Zeitpunkt möglicherweise verworfen wird, wenn dies sinnvoll ist. Das ist ein bisschen weniger Code seitens des Codierers im Austausch für eine Laufzeit, die etwas mehr Heben bewirkt.
quelle
Die beste Antwort ist tatsächlich in der Frage enthalten: Zeiger sind für die Programmierung auf niedriger Ebene. Zugegeben, wenn Sie C verwenden, ist das Nichtverwenden von Zeigern wie das Programmieren mit einer Hand hinter dem Rücken, aber die Antwort darauf ist, stattdessen eine höhere Sprache zu verwenden.
quelle
Zeiger bieten einen Einblick in die Maschine, die für die interessanteste Programmierung erforderlich ist. Die meisten modernen Sprachen verbergen einfach die grobkörnigen Teile vor Ihnen.
quelle