Frage

In einem C ++ Projekt, das intelligente Zeiger, wie boost::shared_ptr verwendet, was ist eine gute Philosophie Design in Bezug auf die Verwendung von " this "?

Beachten Sie, dass:

  • Es ist gefährlich, den Rohzeiger in jedem Smart-Pointer für die spätere Verwendung enthalten zu speichern. Sie haben die Kontrolle über Objektlöschung gegeben und vertrauen auf dem Smart-Pointer es zur richtigen Zeit zu tun.

  • Nicht-statische Klassenmitglieder eigen einen verwenden this Zeiger. Es ist ein Rohzeiger und das kann nicht geändert werden.

Wenn ich jemals speichern this in einer anderen Variablen oder übergeben Sie es an eine andere Funktion, die möglicherweise für eine spätere speichern könnte oder es in einen Rückruf binden, Ich schaffe Fehler, die eingeführt werden, wenn jemand einen gemeinsamen Zeiger auf meiner Klasse zu machen entscheidet .

Da, wenn es jemals für mich geeignet explizit einen this Zeiger benutzen? Gibt es Design-Paradigmen, die Fehler im Zusammenhang mit diesem verhindern?

War es hilfreich?

Lösung

Während ich keine allgemeine Antwort oder ein Idiom haben, ist boost::enable_shared_from_this . Es ermöglicht Ihnen, eine shared_ptr zu bekommen ein Objekt verwalten, die bereits von shared_ptr verwaltet wird. Da in einer Memberfunktion Sie keinen Hinweis auf diese Verwaltung Shared_ptr die haben, ist enable_shared_ptr können Sie eine shared_ptr Instanz erhalten und weitergeben, wenn Sie die diesen Zeiger übergeben müssen.

Aber das wird das Problem der Weitergabe this aus dem Konstruktor nicht lösen, da zu diesem Zeitpunkt wird keine Shared_ptr noch Ihr Objekt zu verwalten.

Andere Tipps

Falsche Frage

  

In einem C ++ Projekt, die Smart-Pointer verwendet

Das Problem hat nichts wirklich mit Smart-Pointer zu tun. Es ist nur über das Eigentum.

Smart-Pointer sind nur Werkzeuge

Sie ändern nichts WRT das Konzept des Eigentums, esp. die Notwendigkeit, gut definierte Eigentum in Ihrem Programm , die Tatsache, dass das Eigentum freiwillig übertragen werden kann, kann aber nicht von einem Kunden entnommen werden.

Sie müssen verstehen, dass intelligente Zeiger (auch Schlösser und andere RAII Objekte) einen Wert und eine Beziehung WRT dieser Wert zugleich darstellen. A shared_ptr ist eine Referenz auf ein Objekt und stellt eine Beziehung: Das Objekt muss nicht vor diesem shared_ptr zerstört werden, und wenn diese shared_ptr zerstört wird, wenn es die letzte Aliasing Diese Aufgabe wird, muss das Objekt sofort zerstört werden. (unique_ptr kann als Spezialfall von shared_ptr betrachtet werden, wo es Null Aliasing per Definition, so dass der unique_ptr ist immer die letzte ein Objekt Aliasing).

Warum sollten Sie intelligente Zeiger verwenden

Es wird empfohlen, intelligente Zeiger zu verwenden, da sie eine Menge mit nur Variablen und Funktionen Erklärungen ausdrücken.

Smart-Pointer kann nur ein gut definiertes Design auszudrücken, sie die Notwendigkeit nicht wegnehmen Eigentum zu definieren. Im Gegensatz dazu nimmt die Garbage Collection die Notwendigkeit weg zu definieren, die für Speicherfreigabe verantwortlich ist. (Aber nehmen Sie nicht die Notwendigkeit weg zu definieren, die für andere Ressourcen clean-up verantwortlich ist.)

Auch in nicht-rein funktionalen Sprachen Müll gesammelt, müssen Sie Eigentum deutlich machen: Sie wollen nicht den Wert eines Objekts zu überschreiben, wenn andere Komponenten noch den alten Wert benötigen. Dies ist insbesondere wahr in Java, in dem das Konzept des Eigentums an änderbarer Datenstruktur ist äußerst wichtig, in Gewinden Programme.

Was ist roh Zeiger?

Die Verwendung eines Rohzeiger bedeutet nicht, es gibt keinen Besitz. Es ist einfach nicht durch eine variable Erklärung beschrieben. Es kann in den Kommentaren beschrieben, in Ihrem Design-Dokumente, etc.

Das ist, warum viele C ++ Programmierer berücksichtigen, dass rohe Zeiger anstelle des angemessenen Smart-Pointer verwendet, ist inferior :, weil es weniger ausdrucksvoll ist (ich habe die Begriffe „gut“ und „schlecht“ absichtlich vermieden). Ich glaube, dass der Linux-Kernel besser lesbar mit einigem C ++ würde Beziehungen ausdrücken Objekte.

Sie können ein spezielles Design mit oder ohne intelligente Zeiger implementieren. Die Implementierung, die Smart-Pointer verwendet wird in geeigneter Weise überlegen von Programmierern vieler C ++ in Betracht gezogen werden.

Ihre eigentliche Frage

  

In einem C ++ Projekt, was ist eine gute Design-Philosophie in Bezug auf der Verwendung von "this"?

Das ist schrecklich vage.

  

Es ist gefährlich, den Rohzeiger für eine spätere Verwendung zu speichern.

Warum müssen Sie auf einen Zeiger für den späteren Gebrauch?

  

Sie haben die Kontrolle über Objektlöschung aufgegeben und Vertrauen in der verantwortliche Komponente es zur richtigen Zeit zu tun.

Tatsächlich ist eine Komponente für die Lebensdauer der Variablen verantwortlich. Sie können die Verantwortung nicht übernehmen. Sie übertragen werden muss,

  

Wenn ich jemals dieses Geschäft in eine andere Variable oder übergeben Sie es an eine andere Funktion, die es potenziell speichern könnten für eine spätere oder binden es in einem Rückruf, Ich erstelle Fehler, die eingeführt werden, wenn jemand entscheidet, meine Klasse zu verwenden.

Natürlich, da der Anrufer nicht darüber informiert, dass die Funktion einen Zeiger verbergen und später ohne die Steuerung des Anrufers verwenden, erstellen Sie Fehler.

Die Lösung ist offensichtlich entweder:

  • Übertragung Verantwortung für die Lebensdauer des Objekts auf die Funktion
  • zu handhaben
  • sicherstellen, dass der Zeiger nur dann gespeichert wird und unter der Kontrolle des Anrufers
  • verwendet

Nur in der frste Fall, könnte man mit einem Smart-Pointer in der Klassenimplementierung enden.

Die Quelle des Problems

Ich denke, dass Ihr Problem ist, dass Sie schwer zu Erschwerend kommt mit Smart-Pointer versuchen. Intelligente Zeiger sind Werkzeuge, die Dinge einfacher zu machen, nicht härter. Wenn intelligente Zeiger Ihre Spezifikation komplizieren, überdenken Sie dann Ihre spec in der Bezeichnung der einfachen Dinge.

Versuchen Sie nicht, intelligente Zeiger als eine Lösung einzuführen, bevor Sie ein Problem haben.

Einführung Nur intelligente Zeiger ein bestimmtes gut definierte Problem zu lösen. Weil Sie kein bestimmtes gut definierten Problem beschreiben, ist es nicht möglich, eine spezifische Lösung (einschließlich Smart-Pointer oder nicht) zu diskutieren.

Ein Beispiel für eine korrekte Verwendung ist return *this; in Funktionen wie operator ++ () und operator << ().

Wenn Sie eine Smart-Pointer-Klasse verwenden, sind Sie richtig, dass gefährlich ist direkt „this“ aussetzen. Es gibt einige Zeiger Klassen boost::shared_ptr<T> bezogen, die von Nutzen sein kann:

  • boost::enable_shared_from_this<T>
    • Bietet die Möglichkeit, ein Objekt zu haben, einen gemeinsamen Zeiger auf sich selbst zurück, die die gleichen Bezugs Zähldaten als vorhandenen freigegebenen Zeiger auf das Objekt
    • verwendet
  • boost::weak_ptr<T>
    • arbeitet Hand in Hand mit freigegebenen Zeiger, aber keinen Verweis auf das Objekt halten. Wenn alle freigegebenen Zeiger gehen weg und das Objekt freigegeben wird, wird ein schwacher Zeiger der Lage zu sagen, dass das Objekt nicht mehr existiert und kehren Sie anstelle eines Zeigers auf ungültige Speicher NULL. Sie können schwachen Zeiger verwenden, um freigegebene Zeiger auf ein gültiges Referenz-Objekt gezählt zu erhalten.

Keiner von ihnen ist narrensicher, natürlich, aber sie werden zumindest machen Sie Ihren Code stabiler und sicherer, während angemessenen Zugang bereitstellt und einen Referenzzähler für Ihre Objekte.

Wenn Sie this verwenden müssen, es nur explizit verwenden. Intelligente Zeiger wickeln nur Zeiger der Objekte, die sie besitzen - entweder und exklusiv (unique_ptr) oder in einer gemeinsamen Weise (shared_ptr).

Ich mag persönlich verwenden, um die diese Zeiger, wenn Membervariablen der Klasse zugreifen. Zum Beispiel:

void foo::bar ()
{
    this->some_var += 7;
}

Es ist nur eine harmlose Frage des Stils. Einige Leute mögen es, somepeople nicht.

Aber mit den diesen Zeigern für jede andere Sache ist wahrscheinlich, Probleme zu verursachen. Wenn Sie wirklich Lust Dinge damit zu tun brauchen, sollten Sie wirklich Ihr Design überdenken. Ich sah einmal einige Code, der im Konstruktor einer Klasse, es gespeichert woanders die diesen Zeiger auf einen anderen Zeiger zugeordnet! Das ist einfach verrückt, und ich kann nicht immer denken, einen Grund, das zu tun. Der gesamte Code war ein großes Durcheinander, übrigens.

Können Sie uns sagen, was genau wollen Sie mit dem Zeiger zu tun?

Eine weitere Option ist mit aufdringlichen intelligenten Zeigern und die Referenzzählung innerhalb des Objekts selbst, nicht die Zeiger zu kümmern. Dies erfordert ein bisschen mehr Arbeit, aber es ist tatsächlich effiziente und einfach zu steuern.

Ein weiterer Grund, um diese zu passieren, wenn Sie eine zentrale Registrierung aller Objekte behalten möchten. Im Konstruktor ruft ein Objekt eine statische Methode der Registrierung mit diesem. Sein nützlich für verschiedene Publish / Subscribe-Mechanismen, oder wenn Sie nicht wollen, die Registrierung Kenntnisse benötigen, welche Objekte / Klassen im System vorhanden sind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top