it-swarm-eu.dev

Warum werden Zeiger beim Codieren mit C ++ nicht empfohlen?

Ich habe von irgendwoher gelesen, dass es bei Verwendung von C++ empfohlen wird, keine Zeiger zu verwenden. Warum sind Zeiger so eine schlechte Idee, wenn Sie C++ verwenden. Was ist für C-Programmierer, die an die Verwendung von Zeigern gewöhnt sind, die bessere Alternative und Vorgehensweise in C++?

45
Joshua Partogi

Ich denke, sie bedeuten, dass Sie intelligente Zeiger anstelle von regulären Zeigern verwenden sollten.

In der Informatik ist ein intelligenter Zeiger ein abstrakter Datentyp, der einen Zeiger simuliert und gleichzeitig zusätzliche Funktionen wie die automatische Speicherbereinigung oder die Überprüfung von Grenzen bereitstellt. Diese zusätzlichen Funktionen sollen Fehler reduzieren, die durch den Missbrauch von Zeigern verursacht werden, während die Effizienz erhalten bleibt. Intelligente Zeiger verfolgen normalerweise die Objekte, auf die sie zum Zweck der Speicherverwaltung zeigen.

Der Missbrauch von Zeigern ist eine Hauptursache für Fehler: Die ständige Zuweisung, Freigabe und Referenzierung, die von einem mit Zeigern geschriebenen Programm durchgeführt werden muss, birgt das Risiko, dass Speicherlecks auftreten. Intelligente Zeiger versuchen, Speicherlecks zu verhindern, indem sie die Freigabe von Ressourcen automatisch vornehmen: Wenn der Zeiger (oder der letzte in einer Reihe von Zeigern) auf ein Objekt zerstört wird, z. B. weil er außerhalb des Gültigkeitsbereichs liegt, wird auch das spitze Objekt zerstört.

In C++ liegt der Schwerpunkt auf der Speicherbereinigung und der Verhinderung von Speicherlecks (um nur zwei zu nennen). Zeiger sind ein wesentlicher Bestandteil der Sprache, daher ist es so gut wie unmöglich, sie nicht zu verwenden, außer in den meisten Programmen.

58
jmq

Da ich derjenige bin, der die Polemik veröffentlicht hat "benutze keine fickenden Zeiger" Ich denke, ich sollte hier einen Kommentar abgeben.

Erstens repräsentiert es als Polemik offensichtlich einen extremen Standpunkt. Es gibt sind definitiv legitime Verwendungen von (rohen) Zeigern. Aber ich (und viele professionelle C++ - Programmierer) behaupten, dass diese Fälle äußerst selten sind. Aber was wir wirklich meinen, ist Folgendes:

Zuerst:

Rohzeiger dürfen unter keinen Umständen eigenen Speicher besitzen.

Hier bedeutet "eigener Speicher" im Wesentlichen, dass irgendwann delete auf diesem Zeiger aufgerufen wird (aber es ist allgemeiner als das). Diese Anweisung kann sicher als absolut angesehen werden. Die Ausnahme nur ist, wenn Sie Ihren eigenen intelligenten Zeiger (oder einen anderen) implementieren Speicherverwaltungsstrategie). Und selbst dort sollten Sie normalerweise still einen intelligenten Zeiger auf niedriger Ebene verwenden.

Der Grund dafür ist ganz einfach: Rohzeiger, die Speicher besitzen, führen zu einer Fehlerquelle. Und diese Fehler sind in vorhandener Software sehr häufig: Speicherlecks und doppeltes Löschen - beides eine direkte Folge des unklaren Ressourcenbesitzes (aber in die entgegengesetzte Richtung).

Dieses Problem kann praktisch kostenlos vollständig beseitigt werden, indem einfach intelligente Zeiger anstelle von rohen Zeigern verwendet werden (Vorbehalt: Dies erfordert natürlich immer noch Nachdenken; gemeinsame Zeiger können führen zu Zyklen und damit einmal wieder zu Speicherlecks - dies ist jedoch leicht zu vermeiden).

Zweite:

Die meisten Verwendungen von Zeigern in C++ sind nicht erforderlich.

Im Gegensatz zu anderen Sprachen unterstützt C++ die Wertesemantik sehr stark und benötigt einfach keine Indirektion von Zeigern. Dies wurde nicht sofort erkannt - in der Vergangenheit wurde C++ erfunden, um eine einfache Objektorientierung in C zu ermöglichen, und stützte sich stark auf die Erstellung von Objektgraphen, die durch Zeiger verbunden waren. In modernem C++ ist dieses Paradigma jedoch selten die beste Wahl, und moderne C++ - Redewendungen benötigen häufig überhaupt keine Zeiger . Sie arbeiten mit Werten und nicht mit Zeigern.

Leider hat sich diese Nachricht in großen Teilen der C++ - Benutzergemeinschaft immer noch nicht durchgesetzt. Infolgedessen ist der größte Teil des geschriebenen C++ - Codes immer noch mit überflüssigen Zeigern übersät, die den Code komplex, langsam und fehlerhaft/unzuverlässig machen.

Für jemanden, der sich mit modernem C++ auskennt, ist es klar, dass Sie sehr selten any Zeiger benötigen (entweder intelligent oder roh; außer wenn Sie sie als Iteratoren verwenden). Der resultierende Code ist kürzer, weniger komplex, lesbarer, oft effizienter und zuverlässiger.

97
Konrad Rudolph

Ganz einfach, weil Ihnen Abstraktionen zur Verfügung stehen, die die temperamentvolleren Aspekte der Verwendung von Zeigern verbergen, z. B. den Zugriff auf den Rohspeicher und das Aufräumen nach Ihren Zuweisungen. Mit intelligenten Zeigern, Containerklassen und Entwurfsmustern wie RAII wird die Verwendung von Rohzeigern verringert. Wie bei jeder Abstraktion sollten Sie jedoch verstehen, wie sie tatsächlich funktionieren, bevor Sie über sie hinausgehen.

15
Ed S.

Relativ einfach lautet die C-Mentalität "Haben Sie ein Problem? Verwenden Sie einen Zeiger". Sie können dies in C-Zeichenfolgen, Funktionszeigern, Zeigern als Iteratoren, Zeigern auf Zeigern und ungültigen Zeigern sehen - selbst in den frühen Tagen von C++ mit Elementzeigern.

In C++ können Sie jedoch Werte für viele oder alle dieser Aufgaben verwenden. Benötigen Sie eine Funktionsabstraktion? std::function. Es ist ein Wert, der eine Funktion ist. std::string? Es ist ein Wert, das ist eine Zeichenfolge. Sie können ähnliche Ansätze in ganz C++ sehen. Dies erleichtert die Analyse des Codes sowohl für Menschen als auch für Compiler erheblich.

11
DeadMG

Einer der Gründe ist die zu breite Anwendung von Zeigern. Sie können für die Iteration über Container verwendet werden, um das Kopieren großer Objekte beim Übergeben an die Funktion, das nicht triviale Lebensdauermanagement, den Zugriff auf zufällige Speicherplätze usw. zu vermeiden. Sobald Sie sie für einen bestimmten Zweck verwendet haben, werden andere Funktionen verfügbar sofort unabhängig auf Absicht.

Durch die Auswahl eines Tools für den genauen Zweck wird Code einfacher und die Absicht besser sichtbar - Iteratoren für Iterationen, intelligente Zeiger für die Lebensdauerverwaltung usw.

10
maxim1000

Neben den bereits aufgeführten Gründen gibt es einen offensichtlichen: bessere Optimierungen. Die Aliasing-Analyse ist in Gegenwart einer Zeigerarithmetik viel zu kompliziert, während Referenzen auf einen Optimierer hinweisen, sodass eine viel tiefere Aliasing-Analyse möglich ist, wenn nur Referenzen verwendet werden.

3
SK-logic

Neben dem Risiko von Speicherverlusten, die durch @ jmquigley-Zeiger und Zeigerarithmetik angegeben werden, kann dies als problematisch angesehen werden, da Zeiger können überall im Speicher zeigen "schwer zu findende Fehler" und "Sicherheitslücken" verursachen.

Deshalb wurden sie in C # und Java fast aufgegeben.

2
k3b