Pimpl mit smart ptr - Warum Konstruktor / Destruktor benötigt [duplizieren]

8

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?

    
meddle0106 11.02.2014, 10:27
quelle

1 Antwort

11

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.

    
Sebastian Redl 11.02.2014, 10:32
quelle

Tags und Links