Frage

Wie sind Objekte im Speicher in C ++ gespeichert?

Für eine regelmäßige Klasse wie

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };

Verwenden eines Zeigers von Objekt als ein Array verwendet werden kann, i1 zuzugreifen wie folgt?

((Object*)&myObject)[0] === i1?

Andere Fragen zu SO scheinen darauf hinzudeuten, dass eine Struktur zu einem Zeiger Gießen für POD-Typen auf das erste Element verweisen. Wie unterscheidet sich für Klassen mit Konstrukteuren, wenn überhaupt? Auch in welcher Weise ist es anders für Nicht-POD-Typen?

Edit:

Im Speicher wäre daher die obige Klasse wie die folgenden gelegt werden?

[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]
War es hilfreich?

Lösung

Fast. Sie werfen auf ein Objekt * und vernachlässigt eine Adresse zu übernehmen. Lassen Sie uns wieder fragen, wie die folgenden:

((int*)&myObject)[0] == i1

Sie haben mit Annahmen wie diese wirklich vorsichtig sein. Wie Sie die Struktur definiert haben, sollten diese Sie stoßen wahrscheinlich in jedem Compiler wahr sein. Aber alle möglichen anderer Eigenschaften des Objekts (die Sie von Ihrem Beispiel weggelassen haben) wird, wie schon andere gesagt, macht es nicht-POD und konnte (möglicherweise in einer Compiler-abhängigen Art und Weise) macht die obige Aussage nicht wahr.

Beachten Sie, dass ich nicht so schnell sein würde, Ihnen sagen, es würde funktionieren, wenn Sie i3 gefragt hatte - in diesem Fall auch für Normal POD, Ausrichtung oder endianness könnte leicht schrauben Sie oben

.

In jedem Fall sollten Sie diese Art der Sache zu vermeiden, wenn möglich. Auch wenn es funktioniert jetzt, wenn Sie (oder sonst jemand, der nicht versteht, dass Sie diesen Trick tun) jemals ändert sich die Struktur um oder fügt neue Felder, wird dieser Trick in allen Orten, scheitern Sie es verwendet haben, die nur schwer zu finden.

Antwort auf Ihre edit: Wenn das Ihre ganze Klassendefinition ist, und du bist einer der Mainstream-Compiler mit Standardoptionen, und läuft auf einem x86-Prozessor, dann ja, Sie haben wahrscheinlich erraten die richtige Speicherlayout. Aber Wahl von Compiler, Compiler-Optionen und verschiedener CPU-Architektur könnte Ihre Annahmen leicht entkräften.

Andere Tipps

Klassen ohne virtuelle Mitglieder und ohne Vererbung werden wie structs im Speicher angelegt. Aber, wenn Sie beginnen Vererbungsebenen Dinge immer knifflig und es kann schwer herauszufinden, was um die Dinge in Erinnerung sind (insbesondere Mehrfachvererbung).

Wenn Sie virtuelle Mitglieder haben, haben sie eine „V-Tabelle“ in Erinnerung, die Zeiger auf die eigentliche Funktion enthält, die auf der Vererbungshierarchie der Klasse basiert erstellt wird.

Unter dem Strich: greift nicht Klassen auf diese Weise überhaupt, wenn Sie es vermeiden können (und auch sie nicht memset oder sie MEMCPY). Wenn Sie dies tun muss (warum?) Dann darauf achten, dass Sie genau wissen, wie Sie Ihre Klassenobjekte im Speicher sein werden und vorsichtig sein Erbe zu vermeiden.

Es ist der Unterschied, dass dieser Trick für POD-Typen nur gültig ist. Das ist wirklich alles, was es ist. Der Standard legt fest, dass diese Besetzung für einen POD ist gültig, aber übernimmt keine Garantie darüber, was passiert mit nicht-POD-Typen.

Es hängt wirklich von dem Compiler, oder besser gesagt, ist es den Compiler überlassen, um das Speicherlayout zu bestimmen.

Zum Beispiel kann eine Mischung aus öffentlichen, privaten und geschützten Membervariablen so ausgelegt werden könnte, dass jede Zugangsart angrenzt. Oder abgeleiteten Klassen könnten Membervariablen verschachtelt mit ungenutztem Raum in der Superklasse haben.

Die Dinge werden schlimmer mit virtueller Vererbung, wo die praktisch geerbt Basisklassen verlegt werden können irgendwo im Speicher für diese bestimmte Instanz zuzugeordnet.

POD ist anders, weil es mit C kompatibel sein muss.

In der Regel, was zählt, ist nicht, ob die Klasse einen Konstruktor hat: was zählt, ist, ob die Klasse keine virtuellen Methoden hat. Einzelheiten Google für 'VTable' und 'vptr'.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top