In diesem Ich brauche C ++ Array-Klasse Vorlage, die eine feste Größe ist, stack-basiert und erfordert keine Standardkonstruktor Antwort Ich postete ein Stück Code, der die Platzierung neu mit Char-Array verwendet . Für mich ist das etwas absolut Normales. Aber nach den Kommentaren ist dieser Code falsch.
Kann jemand das genauer erklären?
Insbesondere was mit dem Array schief gehen kann. Was ich aus den Kommentaren verstehe, ist, dass T x[size];
möglicherweise nicht in char x[size*sizeof(T)];
passt. Ich glaube nicht, dass das wahr ist.
BEARBEITEN:
Ich bin nur mehr und mehr verwirrt. Ich weiß, welche Ausrichtung bei Strukturen ist. Ja, wenn Sie eine Struktur haben, beginnen die Attribute mit verschiedenen Offsets, was Sie vielleicht denken.
OK, jetzt sind wir wieder bei Arrays. Sie sagen mir, dass T x[size];
die gleiche Größe wie char x[size*sizeof(T)];
hat, aber ich kann nicht auf das char-Array als T-Array zugreifen, da es eine gewisse Ausrichtung geben könnte. Wie kann es eine Ausrichtung geben, wenn die Arrays die gleiche Größe haben?
EDIT 2:
OK, ich bekomme es endlich, es kann an einer falschen Adresse beginnen.
EDIT 3:
Thx jeder, du kannst aufhören zu posten :-) Puh, diese Summe hat mich umgehauen. Ich habe nie realisiert, dass das möglich ist.
Ein T x[size]
-Array passt immer genau in size * sizeof(T)
bytes, was bedeutet, dass char buffer[size*sizeof(T)]
immer genau genug ist, um ein solches Array zu speichern.
Das Problem in dieser Antwort, so wie ich es verstanden habe, war, dass Ihr char
-Array nicht garantiert richtig ausgerichtet ist, um das Objekt vom Typ T
zu speichern. Nur malloc
-ed / new
-ed-Puffer sind garantiert korrekt ausgerichtet, um alle Standarddatentypen kleinerer oder gleicher Größe (oder Datentypen, die aus Standarddatentypen bestehen) zu speichern, aber wenn Sie explizit ein% co_de deklarieren % array (als lokales Objekt oder Mitgliedsteilobjekt) gibt es keine solche Garantie.
Alignment bedeutet, dass es auf irgendeiner Plattform streng (oder nicht so streng) erforderlich ist, alle char
-Objekte beispielsweise auf einer 4-Byte-Grenze zuzuweisen. Z.B. Sie können ein Objekt int
an der Adresse int
oder 0x1000
platzieren, aber Sie können kein Objekt 0x1004
an der Adresse int
platzieren. Oder, genauer gesagt, Sie können das tun, aber alle Versuche, auf diesen Speicherort als Objekt vom Typ 0x1001
zuzugreifen, führen zu einem Absturz.
Wenn Sie ein beliebiges Array int
erstellen, weiß der Compiler nicht, wofür Sie es verwenden möchten. Es kann entscheiden, dieses Array an der Adresse char
zu platzieren. Aus dem obigen Grund wird ein naive Versuch, ein 0x1001
-Array in einem solchen nicht ausgerichteten Puffer zu erstellen, fehlschlagen.
Die Ausrichtungsanforderungen für einige Plattformen sind streng, was bedeutet, dass alle Versuche, mit falsch ausgerichteten Daten zu arbeiten, zu Laufzeitfehlern führen. Auf einigen anderen Plattformen sind sie weniger streng: Der Code wird funktionieren, aber die Leistung wird darunter leiden.
Die Notwendigkeit für die richtige Ausrichtung bedeutet manchmal, dass Sie, wenn Sie ein int
-Array in einem beliebigen int
-Array erstellen wollen, den -Schnitt am Anfang eines char
-Arrays haben müssen vorwärts vom Anfang des int
-Arrays. Wenn sich beispielsweise das Array char
bei char
befindet, haben Sie keine andere Wahl als das Array 0x1001
vor Ort aus der Adresse int
zu starten (das ist das Element 0x1004
mit dem Index 3 ). Um den Endteil des verschobenen char
-Arrays unterzubringen, müsste das int
-Array 3 Bytes größer sein als das, was der char
auswertet. Aus diesem Grund ist die Originalgröße möglicherweise nicht ausreichend.
Wenn Ihr size * sizeof(T)
-Array in keiner Weise ausgerichtet ist, benötigen Sie im Allgemeinen ein Array von char
bytes, um ein ausgerichtetes (dh möglicherweise verschobenes) Array von Objekten vom Typ size * sizeof(T) + A - 1
unterzubringen, die ausgerichtet werden müssen bei A-Byte-Grenze.
T
kann anders ausgerichtet sein als ein char.
auch, itanium abi (zum Beispiel) gibt Cookies für Nicht-pod-Array an, so dass es weiß, wie viele Elemente beim Löschen durchlaufen werden müssen (um die Destruktoren aufzurufen). Die Zuweisung über neue ist wie folgt (Iirc):
%Vor%, so dass die Zuordnung für ein 16 Byte ausgerichtetes Objekt lautet:
%Vor%char kann auf einigen Systemen auf 1 ausgerichtet werden, also ... sehen Sie, wo die Fehlausrichtung und Größenprobleme passen. Built-in-Typen brauchen ihre dtors nicht aufgerufen, sondern alles andere.
char x[size*sizeof(T)];
berücksichtigt möglicherweise Ausrichtung nicht, wobei T x [Größe]; werden. alignment (2) kann auch sehr wichtig sein, wenn Sie mit SSE-Typen arbeiten, die eine 16-Byte-Ausrichtung erfordern
Bei einigen Systemen muss der Speicherzugriff "ausgerichtet" sein. Der Einfachheit halber bedeutet dies, dass die Adresse ein Vielfaches einer ganzen Zahl sein muss, die "Alignemnt-Anforderung" des Typs genannt wird (siehe 3.9 / 5 des C ++ - Standards).
Nehmen wir zum Beispiel an, sizeof(int) == 4
:
Die Adresse von charptr ist kein Vielfaches von 4. Wenn also int
eine Ausrichtungsanforderung von 4 auf Ihrer Plattform hat, hat das Programm ein undefiniertes Verhalten.
Ähnlich:
%Vor% Die Adresse von ra
ist nicht garantiert ein Vielfaches von 4.
Das ist aber OK:
%Vor% weil new
garantiert, dass char-Array-Zuordnungen für jeden Typ ausgerichtet sind, der klein genug ist, um in die Zuweisung (5.3.4 / 10) zu passen.
Wenn Sie sich von automatischen Systemen entfernen, können Sie leicht erkennen, warum der Compiler keine Datenelemente ausrichtet. Überlegen Sie:
%Vor% Wenn der Standard garantiert, dass second
4-ausgerichtet ist (immer noch vorausgesetzt, dass int
4-ausgerichtet ist), dann müsste die Größe dieser Struktur mindestens 16 sein (und ihre Ausrichtung Anforderung mindestens 4) . Da der Standard tatsächlich geschrieben wird, darf ein Compiler diese Strukturgröße 12 ohne Auffüllung und keine Ausrichtungsanforderung erhalten.
§5.3.4 / 10:
Ein neuer Ausdruck übergibt den Betrag von Speicherplatz für die Zuweisung angefordert Funktion als erstes Argument des Typs %Code%. Dieses Argument soll sein nicht weniger als die Größe des Objekts erschaffen werden; es kann größer sein als die Größe des Objekts, das erstellt wird nur wenn das Objekt ein Array ist. Zum Arrays von Char und unsigned char, die Unterschied zwischen dem Ergebnis der new-expression und die Adresse zurückgegeben von der Zuordnungsfunktion soll ein ganzzahliges Vielfaches von sein strengste Ausrichtung Anforderung (3.9) eines beliebigen Objekttyps, dessen Größe ist nicht größer als die Größe des Arrays erstellt werden.
Dies ermöglicht die Verwendung von char-Arrays, die mit new für die Platzierungskonstruktion von geeignet große Objekte anderer Arten. Der vorab zugewiesene Puffer muss auf dem Heap zugewiesen werden. Sonst könnte es zu Alignment Problemen kommen.
Tags und Links c++