Zeiger auf Elementfunktion des unvollständigen Typs

8

Ich verstehe nicht, warum das Hinzufügen einer Forward-Deklaration für eine Klasse die Größe ihres Zeigers auf den Member-Typ ändert

%Vor%

Ausgabe VS2013:
4

Aber wenn ich die ersten zwei Zeilen in main () auskommentiere, dann ist die Ausgabe anders:
16
16

Nur ein einfaches Hinzufügen einer Vorwärtsdeklaration vor einer Definition von struct CL erhöht also die Größe eines Zeigers auf CL. Warum? Ich weiß, dass eine Größe des Elementfunktionszeigers von der Struktur eines Typs abhängt (z. B. können virtuelle Funktionen und Basisklassen diese erhöhen), aber warum kann der Operator sizeof auf einen Zeiger auf ein Element eines unvollständigen Typs angewendet werden? Oder kann es nicht? Ich habe es im Standard nicht gefunden

    
user3514538 18.06.2015, 18:43
quelle

1 Antwort

8

Der MSVC-Compiler verwendet verschiedene Größen für Zeiger auf Elementfunktionen als Optimierung. Diese Optimierung verstößt gegen den Standard. Kudos zu Igor Tandetnik Erwähnung von reinterpret_cast in ein MSDN-Formular post , [expr.reinterpret.cast] p10

  

Ein Prvalue vom Typ "pointer to member of X vom Typ T1 " kann sein   explizit in einen prvalue eines anderen Typs "Zeiger auf   Mitglied von Y vom Typ T2 "wenn T1 und T2 beide Funktionstypen sind   oder beide Objekttypen. Der Nullelementzeigerwert wird in konvertiert   der Nullelementzeigerwert des Zieltyps Das Ergebnis von   Diese Konvertierung ist nicht spezifiziert, außer in den folgenden Fällen:

     
  • Konvertieren eines prvalue vom Typ "Zeiger auf Elementfunktion" in einen anderen Zeiger auf Elementfunktionstyp und zurück zu seinem Original   type liefert den ursprünglichen Zeiger auf den Member-Wert.
  •   

Es gibt also eine Roundtrip-Garantie, die dazu führt, dass konforme Implementierungen die gleiche Größe für alle Zeiger auf Member-Funktionstypen verwenden.

Die MSVC-Optimierung wird durchgeführt, wenn /vmb switch eingestellt ist. Für den Fall der Einzelvererbung benötigt der optimierte Zeiger auf die Elementfunktion nur einen void* -Speicher, siehe Das Alte Neue Ding: Zeiger auf Mitgliedsfunktionen sind sehr seltsame Tiere .

Wenn Sie nur den Typ CL weiterleiten und dann eine Pointer-zu-Member-Funktion bilden, wird die Optimierung hoffentlich deaktiviert (leider konnte ich dazu keine Dokumentation finden). Andernfalls erhalten Sie möglicherweise inkonsistente Größen vor und nach der Definition von CL .

Übrigens können Sie in VS2010 inkonsistente Größen für Enumerationen erhalten, wenn Sie sie vorwärts emektieren ohne einen zugrunde liegenden Typ anzugeben und später explizit den zugrunde liegenden Typ für die Definition der Enumeration definieren. Dies funktioniert nur mit aktivierten Spracherweiterungen.

    
dyp 18.06.2015, 19:33
quelle