Betrachten wir folgendes Beispiel (mit c ++ 11)
A.hpp:
%Vor%main.cpp:
%Vor%Standardkonstruktor und Destruktor verwenden. Kompiliert nicht. Folgender Fehler tritt auf:
In der Datei enthalten von /usr/include/c++/4.8/memory:81:02, von A.hpp: 2, aus main.cpp: 2: /usr/include/c++/4.8/bits/unique_ptr.h: In Instantiierung von 'void std :: default_delete & lt; _Tp & gt; :: operator () (_Tp *) const [mit _Tp = A :: AImpl] ': /usr/include/c++/4.8/bits/unique_ptr.h:184:16: erforderlich aus 'std :: unique_ptr & lt; _Tp, _Dp & gt; :: ~ unique_ptr () [mit _Tp = A :: AImpl; _Dp = std :: default_delete] 'A.hpp: 3: 7: Von hier aus erforderlich /usr/include/c++/4.8/bits/unique_ptr.h:65:22: error: invalid Anwendung von 'sizeof' auf unvollständigen Typ 'A :: AImpl'
static_assert (sizeof (_Tp) & gt; 0,
Ein ähnlicher Fehler tritt auf, wenn boost :: scoped_ptr anstelle von std :: unique_ptr verwendet wird. Verstehe ich das richtig - es bedeutet, dass die Vorwärtsdeklaration von AImpl nicht genug ist?
Beim Hinzufügen von Konstruktor und Destruktor funktioniert alles einwandfrei. Was ist der Grund? Liegt es daran, dass die Standardwerte inline sind und die Größe von AImpl nicht angezeigt wird? Und beim Hinzufügen von Konstruktor und Destruktor geht der Compiler davon aus, dass diese Definitionen die Größe von AImpl kennen?
Der unique_ptr
Destruktor muss die vollständige Definition von AImpl
kennen, da er gelöscht wird. Die Frage ist also, wo sitzt der unique_ptr
Destructor? Es ist eine Vorlage, also ist die Frage über den Instanziierungspunkt.
Der Destruktor wird bei der ersten Verwendung instanziiert. Sowohl der Konstruktor als auch der Destruktor der enthaltenden Klasse verwenden ihn (der Konstruktor benötigt ihn, wenn sein Body eine Ausnahme auslöst). Daher wird der unique_ptr
Destruktor instanziiert, wobei A
's Konstruktor oder Destruktor platziert wird, je nachdem, was zuerst eintritt.
Wenn Sie diese speziellen Member als Standard angeben, werden sie unmittelbar nach dem Klassenrumpf generiert, d. h. in der Kopfzeile, wo die Größe von AImpl
nicht bekannt ist.
Wenn Sie sie stattdessen in der Klasse deklarieren und dann Definitionen (Sie können =default
diese Definitionen eingeben) in .cpp
hinter der vollständigen Definition von AImpl
einfügen, wird dort der unique_ptr
Destruktor instanziiert.
Tags und Links c++ c++11 pimpl-idiom