unique_ptr C++: auto_ptr+Vorwärtsdeklaration?




c++ unique_ptr (6)

Ich habe eine Klasse wie diese:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    Inner* m_inner;
};

In der Datei .cpp erstellt der Konstruktor eine Instanz von Inner mit new und der Destruktor delete es. Das funktioniert ziemlich gut.
Jetzt möchte ich diesen Code ändern, um auto_ptr zu verwenden, also schreibe ich:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    std::auto_ptr<Inner> m_inner;
};

Jetzt initialisierte der Konstruktor das auto_ptr und der Destruktor tut nichts.

Aber es funktioniert nicht. Das Problem scheint zu entstehen, wenn ich diese Klasse instanziiere. Ich bekomme diese Warnung:

Warnung C4150: Löschen des Zeigers auf unvollständigen Typ 'Inner'; kein Destruktor genannt

Nun, das ist offensichtlich sehr schlecht und ich verstehe, warum es passiert. Der Compiler weiß nichts über den d'order von Inner wenn er die Vorlage von auto_ptr<Inner> instanziiert

Also meine Frage: Gibt es eine Möglichkeit, auto_ptr mit einer Forward-Deklaration zu verwenden, wie ich es in der Version getan habe, die nur einfache Zeiger verwendet?
Jede Klasse zu deklarieren, zu der ich einen Zeiger deklariere, ist ein großer Ärger und manchmal unmöglich. Wie wird dieses Problem normalerweise behandelt?


Sie müssen die Header-Definition der class Inner in die Datei Cont::~Cont() in der sich die Cont::~Cont() Implementierung befindet. Auf diese Weise haben Sie immer noch eine Forward-Deklaration in dem Header, der die class Cont definiert class Cont und der Compiler sieht die class Inner Definition der class Inner und kann den Destruktor aufrufen.

//Cont.h
class Inner; // is defined in Inner.h
class Cont 
{ 
    virtual ~Cont(); 
    std::auto_ptr<Inner> m_inner;
};

// Cont.cpp
#include <Cont.h>
#include <Inner.h>

Cont::~Cont()
{
}

Diese Frage (Löschen eines Objekts mit einem privaten Destruktor) und diese Frage (wie man eine unvollständige Vorlage schreibt) können Ihnen helfen.


Sie sollten technisch nicht Standardbibliotheksvorlagen mit unvollständigen Typen instanziieren, obwohl ich keine Implementierung weiß, wo dies nicht funktionieren wird. In der Praxis ist Sharptooths Antwort das, was ich auch empfehlen würde.

Es war wirklich nichts falsch daran, einen nackten Zeiger für den impl-Zeiger zu verwenden, solange Sie in Ihrem Destruktor delete aufrufen. Sie sollten wahrscheinlich auch den Kopierkonstruktor und den Zuweisungsoperator implementieren oder deaktivieren.


Stellt sich heraus das Problem tritt nur auf, wenn ich den c'tor inline mache. Wenn ich den c'tor in die cpp lege, ist nach der Deklaration von Inner alles in Ordnung.


Sie können stattdessen boost :: shared_ptr () berücksichtigen. Es hat keine praktischen Nachteile anstelle der Leistung und ist viel freundlicher, Deklarationen weiterzuleiten:

boost::shared_ptr<class NeverHeardNameBefore> ptr;

ist in Ordnung, ohne zusätzliche Erklärungen oben.

shared_ptr tut mehr als auto_ptr, z. B. Referenzzählung, aber es sollte nicht schaden, wenn Sie es nicht brauchen.


Es scheint lächerlich zu sein, aber ich habe das gleiche Problem gelöst, indem ich #include <memory> zur Datei Cont.h hinzugefügt habe.







auto-ptr