Speicherstruktur eines Nur-Funktion-Objekts?

8

Nehmen wir an, wir haben eine Klasse, die so aussieht:

%Vor%

Nun weiß ich, dass Objekte dieser Klasse nur mit den beiden ints im Speicher abgelegt werden. Das heißt, wenn ich einen Vektor von Instanzen der Klasse A mache, gibt es zwei ints für eine Instanz, gefolgt von zwei ints für die zweite Instanz usw. Die Objekte sind POD.

Aber sagen wir mal, die Klasse sieht so aus:

%Vor%

Wie sehen Objekte dieser Klasse im Speicher aus? Wenn ich einen Vektor mit Instanzen von B ... fülle, was ist im Vektor? Mir wurde gesagt, dass nicht-virtuelle Member-Funktionen am Ende als freie Funktionen kompiliert werden, irgendwo völlig unabhängig von den Instanzen der Klasse, in der sie deklariert sind (virtuelle Funktion auch, aber die Objekte speichern eine vtable mit Funktionszeigern) . Dass die Zugriffsbeschränkungen lediglich auf der semantischen, "menschlichen" Ebene liegen. Nur die Datenelemente einer Klasse (und die vtable usw.) bilden tatsächlich die Speicherstruktur von Objekten.

Also, wie sehen Objekte der Klasse B im Speicher aus? Ist es eine Art Platzhalterwert? Etwas muss da sein, ich kann die Adresse des Objekts nehmen. Es muss auf etwas zeigen. Was auch immer es ist, darf der Compiler diese Objekte inline / optimieren und die Methodenaufrufe als normale freie Funktionsaufrufe behandeln? Wenn ich einen Vektor von diesen erzeuge und die gleiche Methode für jedes Objekt anrufe, kann der Compiler den Vektor eliminieren und ihn durch eine Menge normaler Aufrufe ersetzen?

Ich bin nur neugierig.

    
Lucas 30.07.2010, 15:32
quelle

7 Antworten

7

Alle Objekte in C ++ haben garantiert eine Größe von & gt; = 1, so dass jedes Objekt eine eindeutige Adresse hat.

Ich habe es nicht versucht, aber ich würde vermuten, dass der Compiler in Ihrem Beispiel 1 Byte für jedes Funktionsobjekt im Array / Vektor zuweist, aber nicht initialisiert.

    
Ferruccio 30.07.2010, 15:36
quelle
5

Wie Ferruccio sagte, haben alle Objekte in C ++ garantiert eine Größe von mindestens 1. Meistens ist es 1 Byte, füllt aber die Größe der Ausrichtung aus, aber was auch immer.

Wenn es jedoch als Basisklasse verwendet wird, muss kein Leerzeichen ausgefüllt werden, sodass:

%Vor%     
James Curran 30.07.2010 15:43
quelle
4
  

Wie sehen Objekte dieser Klasse im Speicher aus?

Es liegt ganz bei dem Compiler. Eine Instanz einer leeren Klasse muss eine Größe ungleich Null haben, so dass unterschiedliche Objekte unterschiedliche Adressen haben (es sei denn, sie werden als Basisklasse einer anderen Klasse instanziiert, in diesem Fall kann sie überhaupt keinen Platz einnehmen). Normalerweise besteht es aus einem einzelnen nicht initialisierten Byte.

  

Was auch immer es ist, darf der Compiler diese Objekte inline / optimieren und die Methodenaufrufe als normale freie Funktionsaufrufe behandeln?

Ja; Der Compiler muss das Objekt nicht erstellen, es sei denn, Sie machen etwas wie die Adresse. Leere Funktionsobjekte werden in der Standardbibliothek häufig verwendet. Daher ist es wichtig, dass sie keinen unnötigen Overhead verursachen.

    
Mike Seymour 30.07.2010 15:37
quelle
2

Ich habe das folgende Experiment durchgeführt:

%Vor%

Das Ergebnis war 1 (VC ++ 2010)

Es scheint mir, dass die Klasse tatsächlich überhaupt keinen Speicher benötigt, aber dass ein Objekt keine Nullgröße haben kann, da dies keinen semantischen Sinn ergeben würde, wenn Sie beispielsweise seine Adresse nehmen würden. Dies wird durch Ferruccios Antwort bestätigt.

    
Clifford 30.07.2010 15:41
quelle
0

Alles, was ich von nun an sage, ist implementierungsabhängig - aber die meisten Implementierungen stimmen überein.

Wenn die Klasse über virtuelle Methoden verfügt, gibt es ein unsichtbares vtable-Zeigerelement. Das ist bei deinem Beispiel jedoch nicht der Fall.

Ja, der Compiler behandelt einen Mitgliedsfunktionsaufruf wie einen freien Funktionsaufruf, es sei denn, es handelt sich um eine virtuelle Funktion. Auch wenn es sich um eine virtuelle Funktion handelt, kann der Compiler die vtable umgehen, wenn er zum Zeitpunkt des Aufrufs den konkreten Typ kennt. Jeder Aufruf hängt immer noch vom Objekt ab, da ein unsichtbarer this -Parameter mit dem Zeiger des Objekts zum Aufruf hinzugefügt wird.

    
Mark Ransom 30.07.2010 15:40
quelle
0

Ich würde denken, dass sie wie alle Objekte in C ++ aussehen:

  • Jede Instanz der Klasse belegt Platz. Da Objekte in C ++ eine Größe von mindestens 1 haben müssen (sie haben also eindeutige Adressen, wie Ferruccino sagte), werden Objekte, die keine Daten angeben, nicht speziell behandelt.
  • Nicht-virtuelle Funktionen belegen in einer Klasse überhaupt keinen Platz. Sie können vielmehr als Funktionen wie diese gedacht werden:

    %Vor%

Wenn diese Klasse von anderen .cpp -Dateien verwendet werden kann, denke ich, dass diese zu tatsächlichen Klasseninstanzen werden, keine regulären Funktionen.

Wenn Sie möchten, dass Ihre Funktionen einfach frei und nicht an Objekte gebunden sind, können Sie entweder mache sie static oder benutze namespace .

    
Joey Adams 30.07.2010 15:50
quelle
0
  

Mir wurde gesagt, dass nicht-virtuelle Elementfunktionen am Ende als freie Funktionen kompiliert werden, die völlig unabhängig von den Instanzen der Klasse sind, in der sie deklariert sind (virtuelle Funktion auch, aber die Objekte speichern eine vtable mit Funktionszeiger). Dass die Zugriffsbeschränkungen lediglich auf der semantischen, "menschlichen" Ebene liegen. Nur die Datenelemente einer Klasse (und die vtable usw.) bilden tatsächlich die Speicherstruktur von Objekten.

Ja, so funktioniert es normalerweise. Es kann sich lohnen, auf die Unterscheidung hinzuweisen, dass dies im Standard nicht spezifiziert ist, und es nicht erforderlich ist - es macht nur Sinn, solche Klassen im Compiler zu implementieren.

  

Also, wie sehen Objekte der Klasse B im Gedächtnis aus? Ist es eine Art Platzhalterwert? Etwas muss da sein, ich kann die Adresse des Objekts nehmen

Genau. :) Der C ++ - Standard erfordert, dass Objekte mindestens ein Byte belegen, genau aus dem Grund, den Sie sagen. Es muss eine Adresse haben, und wenn ich diese Objekte in ein Array setze, muss ich in der Lage sein, einen Zeiger zu inkrementieren, um "das nächste" Objekt zu bekommen, so dass jedes Objekt eine eindeutige Adresse haben muss und mindestens 1 Byte braucht. (Natürlich haben leere Objekte nicht , um genau 1 Byte zu nehmen. Einige Compiler können aus Leistungsgründen 4 Bytes oder jede andere Größe wählen)

Ein vernünftiger Compiler wird es nicht einmal zu einem Platzhalterwert machen. Warum sollte man einen bestimmten Wert in dieses eine Byte schreiben? Wir können es einfach den Müll enthalten lassen, der beim Erstellen des Objekts enthalten war. Es wird sowieso nie zugegriffen werden. Ein einzelnes Byte wird nur zugewiesen und niemals gelesen oder geschrieben.

    
jalf 30.07.2010 16:53
quelle

Tags und Links