[Gelöst] Empty Base Class Optimisation
-
Nexus schrieb:
Falls
sizeof(int) == 4
ist, gilt 3*3*4 == 36. Du schachtelst ja 3 Objekte mit jeweils 3int
s.Falls du die 40 meinst, wahrscheinlich kann der Compiler leere Basisobjekte nicht so gut wegoptimieren.
Nächstes Mal sollte ich in Ruhe lesen...
Ja, die 40 meine ich. Ich würde gerne genaueres wissen, weil ich ähnliche Konstruktionen in Unions, in der Annahme sie würden gleichviel belegen, verwende und sie merkwürdiges verhalten liefern.
-
Darf ich mal zwischenfragen wozu die genauen Größen der Klassen / Strukturen / Unions überhaupt wichtig sind?
-
Janjan schrieb:
Darf ich mal zwischenfragen wozu die genauen Größen der Klassen / Strukturen / Unions überhaupt wichtig sind?
Egal. Das ist ein Rätsel, das gelöst werden will.
-
Janjan schrieb:
Darf ich mal zwischenfragen wozu die genauen Größen der Klassen / Strukturen / Unions überhaupt wichtig sind?
nun zu beginn, sah ich auch keinen Zusammenhang.
Bekanntlich, nehmen Unions die Größe des Größten Elements an;
Sind die Elemente unterschiedlich groß, können sie auf unterschiedliche Objekte im Speicher Zeigen.Dadurch kann die Datenmanipulation(durch die Obekte des Unions), Unerwartetes verhalten hervorrufen...Edit:
class Test // { ... int A[3]; ... }; union { int A[3][3]; // belegt int * 3 * 3 Test B[3]; // belegt mehr int * 3 * 3 }//haben die Elemente den selben Speicherbereich?
-
Nein, dies kann nicht der Fall sein. In Unions wird garantiert, dass _ALLE_ Elemente an der selben Speicherstelle beginnen.
-
Janjan schrieb:
Nein, dies kann nicht der Fall sein. In Unions wird garantiert, dass _ALLE_ Elemente an der selben Speicherstelle beginnen.
Beginnen , Ja aber nicht Enden.
-
Speed schrieb:
Janjan schrieb:
Nein, dies kann nicht der Fall sein. In Unions wird garantiert, dass _ALLE_ Elemente an der selben Speicherstelle beginnen.
Beginnen , Ja aber nicht Enden.
Das ergibt auch keinen Sinn.
union Foo { char a; int b; };
a und beginnen jeweils an der selben Stelle im Speicher, aber a endet logischerweise 3 bytes früher. Das Union hat die Größe von b, da es das größte Element ist.
-
Warum steht da einmal 40, wo man doch 36 erwarten würde?
-
Janjan schrieb:
Speed schrieb:
Janjan schrieb:
Nein, dies kann nicht der Fall sein. In Unions wird garantiert, dass _ALLE_ Elemente an der selben Speicherstelle beginnen.
Beginnen , Ja aber nicht Enden.
Das ergibt auch keinen Sinn.
union Foo { char a; int b; };
a und beginnen jeweils an der selben Stelle im Speicher, aber a endet logischerweise 3 bytes früher. Das Union hat die Größe von b, da es das größte Element ist.
ja, aber was wenn die Elemente als Synonyme, verwendet werden.
zB konnte im oben genannten Beispiel der Operator[] überladen werden.
-
@ Speed:
Bist du eigentlich sicher, dass duunion
brauchst? Damit handelt man sich nämlich genau solche Probleme ein. Überhaupt ist das Verhalten undefiniert, wenn du von einem anderen Member liest, als dem zuletzt beschriebenen. In C++ benötigt manunion
eigentlich recht selten.Ansonsten hat das Problem weniger mit C++ zu tun als mit deinem Compiler. Womöglich gibts eine Einstellung fürs Padding von Klassen.
-
Ich habe das Gefühl du missbrauchst Unions ganz extrem...
Alle Elemente teilen sich natürlich nicht den gesamten Speicherraum des Unions - das geht auch logischerweise nicht. Ein Datentyp char kann ja nicht plötzlich 20 byte groß sein, nur weil das Union 20 byte groß ist. Alle Member starten lediglich an der selben Adresse.
-
Nexus schrieb:
Ansonsten hat das Problem weniger mit C++ zu tun als mit deinem Compiler.
Ok.
-
Dieser Thread wurde von Moderator/in volkard aus dem Forum C++ in das Forum Compiler- und IDE-Forum verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Nexus schrieb:
@ Speed:
Bist du eigentlich sicher, dass duunion
brauchst? Damit handelt man sich nämlich genau solche Probleme ein. Überhaupt ist das Verhalten undefiniert, wenn du von einem anderen Member liest, als dem zuletzt beschriebenen. In C++ benötigt manunion
eigentlich recht selten.Ansonsten hat das Problem weniger mit C++ zu tun als mit deinem Compiler. Womöglich gibts eine Einstellung fürs Padding von Klassen.
Ich habe meine Gründe, diese Konstruktion zu verwenden, bin sogar gezwungen diese zu nutzen. Das Verhalten ist Definiert und analysiert man meine Klassen, kann man das verhalten nachvollziehen,selbst wenn die Member unerwartete Größen Besitzen.
Die notwendigkeit,ergab sich aus der Praxis und den Performance-ansprüchen und ist auch in vielen anderen Mathe-libs zu beobachten.
Beispiele kann ich, bei nachfrage Später, hier posten aber sinn und unsinn von Unions sind hier offtopic
-
Deine Erwartung das alle Member-Variablen den kompletten Speicherbereich eines Unions verwenden ist unsinnig.
Jede Variable benutzt den Speicher entsprechend ihrer Größe, nicht mehr, nicht weniger. Nur das alle Variablen an der selben Speicherstelle beginnen ist garantiert.
-
Janjan schrieb:
Ein Datentyp char kann ja nicht plötzlich 20 byte groß sein, nur weil das Union 20 byte groß ist. Alle Member starten lediglich an der selben Adresse.
Sollen sie auch nicht.
aber wie siehts mit folgendem Beispiel aus:
class X
{
public:int B[2];
int C[2];};
union
{
int A[4];
X B;
};
-
Undefiniertes Verhalten, da es nicht festgelegt ist, dass alle Member von class in einer Reihe im Speicher liegen. Dein Compiler kann Padding adden, wenn er es als nötig erachtet.
-
Janjan schrieb:
Undefiniertes Verhalten, da es nicht festgelegt ist, dass alle Member von class in einer Reihe im Speicher liegen. Dein Compiler kann Padding adden, wenn er es als nötig erachtet.
zwischen ints? extrem unrealistisch. das scheint mir jetzt paragraphenreiterei zu sein.
-
volkard schrieb:
Janjan schrieb:
Undefiniertes Verhalten, da es nicht festgelegt ist, dass alle Member von class in einer Reihe im Speicher liegen. Dein Compiler kann Padding adden, wenn er es als nötig erachtet.
zwischen ints? extrem unrealistisch. das scheint mir jetzt paragraphenreiterei zu sein.
Es ist unwahrscheinlich, das stimmt. Aber so ist es.
Wenn er ne komplexere Klasse hat (was höchstwahrscheinlich der Fall ist), dann trifft es zu.
Aber in seinem Beispiel wäre es festgelegt, dass X und int an der selben Stelle liegen. Wie die interne Struktur von X ist, ist ja eine vollkommene andere Sache.
-
Janjan schrieb:
volkard schrieb:
Janjan schrieb:
Undefiniertes Verhalten, da es nicht festgelegt ist, dass alle Member von class in einer Reihe im Speicher liegen. Dein Compiler kann Padding adden, wenn er es als nötig erachtet.
zwischen ints? extrem unrealistisch. das scheint mir jetzt paragraphenreiterei zu sein.
Es ist unwahrscheinlich, das stimmt. Aber so ist es.
Wenn er ne komplexere Klasse hat (was höchstwahrscheinlich der Fall ist), dann trifft es zu.
Aber in seinem Beispiel wäre es festgelegt, dass X und int an der selben Stelle liegen. Wie die interne Struktur von X ist, ist ja eine vollkommene andere Sache.
Es ist festgelegt wann sich wo die Member einer klasse, sich im Speicher befinden.
Und genau dass nutzt man aus, und um undefiniertes verhalten auszuschließen dürfen auch nur PODs verwendet werden. Virtuell , Zeiger etc sind in Unions verboten.Aber, Ich Zitiere :
volkard schrieb:
Warum steht da einmal 40, wo man doch 36 erwarten würde?