Ist dies ein nicht definiertes Verhalten oder eine falsch positive Warnung?

8

Betrachten Sie den folgenden Code:

%Vor%

Nun versuche ich, diesen Code mit clang zu kompilieren ...

%Vor%

GCC druckt keine Warnungen, auch nicht mit -Wall -Wextra und -pedantic .

    
Thomas 09.05.2015, 19:50
quelle

2 Antworten

7

Es ist undefiniertes Verhalten. Laut [class.base.init]:

  

In einem nicht delegierenden Konstruktor wird die Initialisierung in der folgenden Reihenfolge ausgeführt:
  - Zuerst und nur für den Konstruktor der am meisten abgeleiteten Klasse (1.8), virtuelle Basisklassen ...
  - Dann werden direkte Basisklassen in der Deklarationsreihenfolge initialisiert, wie sie in der Basisspezifiziererliste erscheinen   (unabhängig von der Reihenfolge der Mem-Initialisierer).
  - Dann werden nicht statische Datenelemente in der Reihenfolge initialisiert, in der sie in der Klassendefinition deklariert wurden   (wieder unabhängig von der Reihenfolge der Mem-Initialisierer).

b wurde nicht initialisiert, wenn die Basisklasse A initialisiert wurde. Die Zuweisung b = 0 ist selbst undefiniertes Verhalten aus dem gleichen Grund - b wurde noch nicht initialisiert, als das aufgerufen wurde. Der Standardkonstruktor würde immer noch nach dem Konstruktor A aufgerufen.

Wenn Sie sicherstellen möchten, dass b zuerst initialisiert wird, ist der typische Ansatz Basis-von-Mitglied-Idiom :

%Vor%     
Barry 09.05.2015, 20:01
quelle
6

In beiden Fällen ruft das Aufrufen einer Memberfunktion vor dem Initialisieren von Basisklassen undefiniertes Verhalten auf. §12.6.2 / 16:

  

Member-Funktionen (einschließlich virtueller Member-Funktionen, 10.3) können sein   rief nach einem Objekt im Bau. In ähnlicher Weise ein Objekt unter   Konstruktion kann der Operand des Operators typeid (5.2.8) oder von a sein    dynamic_cast (5.2.7). Wenn diese Vorgänge jedoch in a ausgeführt werden    ctor-initializer (oder in einer Funktion, die direkt oder indirekt von einem ctor-Initialisierer aufgerufen wird) vor allen mem-Initialisierern   Basisklassen sind abgeschlossen, das Ergebnis der Operation ist   undefiniert. [Beispiel:

%Vor%

Allerdings ist der Zugriff und die Zuweisung zu b selbst in Ordnung, da es eine leere Initialisierung hat und seine Lebensdauer beginnt, sobald Speicher dafür erworben wird (was lange vor dem Aufruf des Konstruktors passiert ist). Daher

%Vor%

ist gut definiert.

    
Columbo 09.05.2015 20:58
quelle