Wie ist das Speicherlayout von dynamischen Arrays?

8
%Vor%

Meine erste Frage ist, wie sieht das intern aus? Was ich vermute:

Wenn Foo eine Klasse ist, dann ist Array ein Zeiger auf ein Array von Pointern von foo-Objekten vector<Foo*> v //c++

Wenn Foo eine Struktur ist, dann ist Array ein Zeiger auf ein Array von Foo-Objekten. vector<Foo> v //c++

Ist ein dynamisches Array in D zusammenhängend im Speicher wie in C ++?

    
Maik Klein 23.08.2014, 10:38
quelle

2 Antworten

13

Ein dynamisches D-Array sieht so aus:

%Vor%

Doing new T[size] führt im Grunde folgendes aus:

%Vor%

Also, ja, die Erinnerung an die Elemente ist zusammenhängend wie in C ++. Der Rest Ihrer Frage bezieht sich auf das, was T ist, und Sie haben recht, was Sie dachten:

Wenn Foo eine Klasse ist, bedeutet das, dass jeder Verweis auf Foo wie ein Zeiger funktioniert, also ist es wie Foo* array in C ++ - T.sizeof , wenn T eine Klasse ist, ist immer gleich void*.sizeof *, die Objekte funktionieren per Referenz. Wenn es eine Struktur ist, ist alles in-Place, wie vector<Foo> in C ++.

Fun fact mit Strukturen btw: sie sind nicht unbedingt im Array wegen der Ausrichtungsprobleme gepackt. Berücksichtigen Sie Folgendes:

%Vor%

Foo.sizeof könnte 6 sein ... aber es ist eigentlich 8, weil die Uint an einer 4-Byte-Grenze ausgerichtet wird, was nach s zwei Bytes der Auffüllung verursacht. Wenn Sie align(1) zum Feld "uint" hinzufügen, überschreiben Sie dies und setzen i direkt neben s in den Speicher. Da es sich jedoch um Arrays handelt, möchten Sie, dass Foo[] elements / noch eine eigene Ausrichtung haben ... Foo.sizeof == 8 noch so, dass Foo[2] eine Größe von 16 hat. Der innere align(1) hat das Padding einfach an das Ende der Struktur verschoben, es wurde jedoch nicht vollständig für die Fälle von Arrays entfernt.

Wenn Sie ein Foo[] wollen, das ohne Padding zwischen Elementen gepackt ist, möchten Sie auch align(1) zu außerhalb der Struktur hinzufügen: align(1) struct Foo { /* ... */ } . Dann Foo.sizeof == 6 und es gibt keine Auffüllung im Array.

  • Wenn Sie die Größe des Objekts selbst erhalten möchten, zum Beispiel, wenn Sie Ihre eigene Version von new MyClass schreiben, gibt es auch eine Möglichkeit, dies zu tun: __traits(classInstanceSize, Foo) . Ссылка Aber D macht Klassen als Referenz, weil es einfacher ist, bei Vorhandensein von Vererbung gesund zu bleiben.

Wie auch immer, ich ging wahrscheinlich detaillierter ins Detail, als Sie eigentlich wollten / brauchten, aber kurz gesagt, Sie haben recht, was mit Foo passiert und ein dynamisches D-Array ist ähnlich aufgebaut wie ein C ++ Vektor. Der größte Unterschied zwischen den beiden ist, dass ein C ++ - Vektor mit dem assign-Operator kopiert werden kann, es ist ein Werttyp. Ein D-Array wird immer nur geschnitten - die Länge und der Zeiger (erinnern Sie sich an das erste Layout in diesem Beitrag) wird kopiert, aber der Inhalt nicht. Sie müssen die Daten explizit in D mit array.dup oder foo[] = bar[] kopieren.

Weiterführende Literatur:

  • Ссылка ("Array-Operationen" ist der foo[] = bar[] -Stück, "Array-Eigenschaften" hat dup und viel mehr drin)
  • Ссылка (siehe die Überschrift "Arrays" - dies beschreibt das länge / ptr-Layout)
  • Ссылка (spricht über das Array selbst gegenüber dem Slice, den Sie bearbeiten, und erklärt einige Interna über Dynamic Array-Speicherverwaltung)

  • Ссылка (Sie können Informationen über die Strukturausrichtung dort finden)

  • Ссылка

Adam D. Ruppe 23.08.2014, 13:02
quelle
4

array selbst ist eine Struktur mit einem size_t length und einem Foo* ptr

Dies ist in Ссылка beschrieben (suche nach Arrays)

Und ja, der Speicher befindet sich im zusammenhängenden Speicher.

    
ratchet freak 23.08.2014 13:00
quelle

Tags und Links