2010-11-23 2 views
5

Ich benutze C++ seit langer Zeit und weiß sehr gut über die Vorsicht bei der Zuweisung und Freigabe von Speicher, insbesondere nicht zu vergessen, nicht verwendete Instanzen zu löschen.Sollte ich Smartpointer für alles verwenden und klassische normale Pointer vergessen?

Jetzt habe ich gerade Boost verwendet und mit einem Problem konfrontiert, bin ich gezwungen, intelligente Zeiger (speziell die shared_ptr) zu verwenden. Also, wenn ich shared_ptr für dieses Problem verwende, sollte ich Smart Pointer für alle meine normale Pointer-Codebasis verwenden?

+0

gibt es keine Leistungseinbuße mit shared_ptr? –

+13

Keine, die Sie erkennen können, wenn Sie diese Frage stellen –

+2

@Terry: Das wurde * perfekt * formuliert. – GManNickG

Antwort

1

Ja. Sie sollten die Boost Smart Pointer für die meisten Dinge verwenden, wenn Sie sie verfügbar haben. Denken Sie daran, während Sie und Ihre Kommentare Zeiger effektiv verwenden können, die Person/Leute, die nach Ihnen kommen, möglicherweise nicht. Die Verwendung der Smartpointer kann und wird (hoffentlich, kann nicht vor schlechtem Code schützen) einige dieser Probleme mildern.

Ich würde auch empfehlen, innerhalb Ihrer Klassen zu verwenden, selbst wenn Ihre Klassen gut entworfen sind. Es wird helfen, sich vor Problemen zu schützen, die der nächste Typ vielleicht vorstellt, wenn er mit einem nackten Zeiger konfrontiert wird. Es wird sie ermutigen, sie auch zu benutzen, zum Beispiel. Das Letzte, was Sie wollen, ist, ein Speicherproblem aufzuspüren, weil jemand vergessen hat, den Zeiger auf NULL zu initialisieren, und es die Prüfung der if-Anweisung übergibt.

+0

Und wenn Sie sie nicht verfügbar haben, verwenden Sie zumindest eine Art von Smart Pointer. – Eclipse

+0

@Eclipse ja, RAII den ganzen Weg. – wheaties

+2

Ich würde empfehlen, shared_ptr nur zu verwenden, wenn Sie es wirklich brauchen, und das sollte selten sein. Aber ja, irgendeine Form von Smart Pointer, definitiv. – Omnifarious

16

Sie sollten intelligente Zeiger vorsichtig verwenden. Sie sind nicht die Silberkugel, wenn es um die Speicherverwaltung geht. Zirkuläre Referenzen sind immer noch ein Problem.

Wenn Sie das Klassendesign machen, denken Sie immer, wer das Eigentum an einem Objekt besitzt (hat die Verantwortung, dieses Objekt zu zerstören). Ergänzen Sie dies gegebenenfalls mit intelligenten Zeigern, aber vergessen Sie nicht das Eigentumsrecht.

+6

+1: Dies ist wahrscheinlich der vernünftigste Ratschlag für die Verwendung von intelligenten Zeigern, die ich je gehört habe. Auch sollten Sie nicht zu "neuen" Dingen verleitet werden, nur weil intelligente Zeiger verfügbar sind. Verwenden Sie storage allocated Objekte, wann immer Sie können, und intelligente Zeiger, um den Rest zu verwalten. –

+1

+1 für die Annahme, dass das Eigentum berücksichtigt werden muss. Es hilft zu bestimmen, welche Speicherverwaltungsstrategie zu verwenden ist (z. B. RAII vs. Smart-Pointer für Referenzzählung) und wie es implementiert werden soll. –

+0

Ich halte Smartpointer für unverzichtbar. Nicht alle Smartpointer sind ':: boost :: shared_ptr'. Sie machen nicht alle Referenzen. Ihr Kommentar darüber, dass Sie mit Ihrem Eigentumsmodell vorsichtig und absichtlich sind, ist ein ausgezeichneter Ratschlag. Aber intelligente Zeiger der einen oder anderen Sorte sind von unschätzbarem Wert für die Handhabung des jeweiligen Eigentumsmodells für dieses bestimmte Datenstück. Ich denke, ':: boost :: shared_ptr' sollte vorsichtig und sparsam verwendet werden. – Omnifarious

-1

Nein. Es hängt davon ab, was Sie tun.

  • Intelligente Zeiger haben einen Leistungsoverhead. In Desktop-Anwendungen ist dies normalerweise kein Problem, aber abhängig davon, was Sie tun, könnte es sein.
  • Intelligente Zeiger funktionieren nicht richtig, wenn Sie Referenzzyklen haben, d. H. A, das auf B und B zeigt, die auf A zeigen, oder sogar etwas, das auf sich selbst zeigt.
+1

Sie haben keinen Leistungsaufwand. – Omnifarious

+3

shared & weak ptr funktioniert gut in einem Zyklus, auf welchen Smart Pointer beziehen Sie sich, wenn Sie sagen, dass es nicht funktioniert –

+1

@Onmifarious - sie haben keine * große * Performance Overhead, aber sie haben einen Overhead. Zum Beispiel haben referenzierte gezählte Smart Pointer Overheads für das Zählen. Für die meisten Zwecke unbedeutend, aber immer noch ein Overhead. – Steve314

5

Ja, Sie sollten Smart Pointer gegenüber bloßen Zeigern für fast alles bevorzugen. Aber das bedeutet nicht, dass Sie ::boost::shared_ptr für die meisten dieser Fälle verwenden sollten. In der Tat denke ich, dass Sie shared_ptr sparsam und vorsichtig verwenden sollten.

Aber für diese Zeiger verwenden Sie nicht shared_ptr für Sie sollte oder verwenden, wenn Sie C++ 0x ::std::unique_ptr haben. Und wenn sie nicht geeignet sind, sollten Sie einen intelligenten Zeigertyp finden.

Jetzt ist dies nicht immer die richtige Antwort, nur fast immer. Intelligente Zeiger sind von unschätzbarem Wert, um Speicherressourcen auch angesichts von Ausnahmen oder anderen derartigen Kuriositäten merklich zu verfolgen und freizugeben.

Es gibt Fälle, in denen Sie entweder Ihre eigene Smart-Pointer-Klasse schreiben oder keine verwenden müssen. Diese Fälle sind sehr selten, aber sie existieren.

Zum Beispiel ist die Verwendung eines intelligenten Zeigers in Ihrer eigenen Smart-Pointer-Klasse wahrscheinlich nicht das Richtige. Das Zeigen auf Stuff, das in einer C-Bibliothek zugeordnet ist, würde wahrscheinlich einen benutzerdefinierten Smart-Pointer erfordern, der free anstelle von delete aufgerufen wird.Vielleicht möchten Sie einen dehnbaren Puffer, den Sie realloc anrufen können und nicht aus irgendeinem Grund eine ::std::vector verwenden möchten.

Aber im Allgemeinen ist ein intelligenter Zeiger (obwohl nicht normalerweise ::boost::shared_ptr (oder in C++ 0x ::std::shared_ptr)) die richtige Antwort auf Ihr Ressourcenverwaltungsproblem.

+0

Sie sollten vorsichtiger sein, wenn Sie std :: auto_ptr empfehlen. Wegen seiner seltsamen Semantik beim Kopieren - die die normalen Erwartungen, wie sich Zuteilung verhält - verletzt, kann es eine Quelle für böse Fehler sein. Tatsächlich finde ich es bei weitem problematischer als nackte Zeiger. – Steve314

+0

@ Steve314 - Ihre und meine Erfahrungen unterscheiden sich in dieser Hinsicht.Obwohl ich denke, C++ 0xs ':: std :: unique_ptr' ist eine viel bessere Implementierung und sollte bevorzugt werden. Ich finde, der Compiler warnt mich normalerweise, wenn ich mit 'auto_ptr' etwas Dummes mache, wenn ich auf' const' Korrektheit acht gebe und 'const' verwende, wo es Sinn macht. – Omnifarious

+3

Sie sollten ** automatische ** (stack-allocated0 Variablen für fast alles verwenden. Für den Rest gibt es intelligente Zeiger und Verweis. Und dann gibt es eine Reihe anderer Verwendungen für bare Zeiger. –

0

Nein, Sie sollten keine intelligenten Zeiger für alles verwenden. Was sollten Sie beachten, wenn new eingeben:

  • Was die Lebensdauer dieses Objekts ist?
  • Welches Objekt besitzt es?
  • Wie wird dieses Objekt seine Lebensdauer verwalten?

Manchmal ist die Lösung ein intelligenter Zeiger, sondern auch die faul Antwort. "Ich möchte nicht daran interessiert sein, herauszufinden, welches Objekt diesen Zeiger besitzt und wie lang es sein sollte, daher mache ich es zu einem shared_pointer!"

Die wichtige Frage ist; Was verwaltet die Lebensdauer dieses Objekts?, kann die Antwort ein intelligenter Zeiger sein, aber oft muss es nicht sein.