Ist die Erinnerung an eine Konstruktion oder Zuordnung eines trivial kopierbaren Typs?
Nehmen wir an, Sie haben ein Objekt vom TypT
und ein passend ausgerichteter Speicherpufferalignas(T) unsigned char[sizeof(T)]
. Wenn du benutztstd::memcpy
aus dem Objekt vom Typ @ kopierT
zumunsigned char
array, wird das als Kopierkonstruktion oder Kopierzuweisung angesehen?
Wenn ein Typ trivial kopierbar ist, aber kein Standardlayout, ist es denkbar, dass eine Klasse wie diese:
struct Meow
{
int x;
protected: // different access-specifier means not standard-layout
int y;
};
könnte so implementiert werden, da der Compiler nicht gezwungen ist, das Standard-Layout zu verwenden:
struct Meow_internal
{
private:
ptrdiff_t x_offset;
ptrdiff_t y_offset;
unsigned char buffer[sizeof(int) * 2 + ANY_CONSTANT];
};
Der Compiler könnte @ speichex
undy
von Meow innerhalb des Puffers an einem beliebigen Teil vonbuffer
, möglicherweise sogar zufällig versetzt innerhalb vonbuffer
, solange sie richtig ausgerichtet sind und sich nicht überlappen. Der Offset vonx
undy
kann sogar bei jeder Konstruktion zufällig variieren, wenn der Compiler dies wünscht. x
könnte nach @ gehy
wenn der Compiler dies wünscht, da der Standard nur Mitglieder desselben Zugriffsspezifizierers benötigt, um in Reihenfolge zu gehen, undx
undy
haben unterschiedliche Zugangsdaten.)
Dies würde die Anforderungen erfüllen, trivial kopierbar zu sein; einmemcpy
würde die ausgeblendeten Versatzfelder kopieren, damit die neue Kopie funktioniert. Aber manche Dinge würden nicht funktionieren. Zum Beispiel einen Zeiger auf @ haltx
über einmemcpy
würde brechen:
Meow a;
a.x = 2;
a.y = 4;
int *px = &a.x;
Meow b;
b.x = 3;
b.y = 9;
std::memcpy(&a, &b, sizeof(a));
++*px; // kaboom
Ist es dem Compiler jedoch wirklich erlaubt, eine trivial kopierbare Klasse auf diese Weise zu implementieren? Dereferenzierungpx
s, sollte nur undefiniertes Verhalten sein, wenna.x
ie Lebensdauer von @ ist abgelaufen. Hat es? Die relevanten Teile des Normentwurfs für N3797 sind zu diesem Thema nicht sehr klar. Dies ist Abschnitt [basic.life] / 1:
DasLebenszei eines Objekts ist eine Runtime-Eigenschaft des Objekts. Ein Objekt soll eine nicht triviale Initialisierung haben, wenn es von einem Klassen- oder Aggregattyp ist und es oder eines seiner Mitglieder von einem anderen Konstruktor als einem trivialen Standardkonstruktor initialisiert wird. Hinweis -Initialisierung durch einen einfachen Konstruktor zum Kopieren / Verschieben ist keine triviale Initialisierung. -end note] Die Lebensdauer eines Objekts vom TypT
beginnt wann:
T
wird erhalten undwenn das Objekt nicht trivial initialisiert wurde, ist die Initialisierung abgeschlossen. Die Lebensdauer eines Objekts vom TypT
endet wenn:
T
ist ein Klassentyp mit einem nicht trivialen Destruktor [class.dtor]), der Destruktoraufruf startet oderder Speicher, den das Objekt belegt, wird wiederverwendet oder freigegeben.Und das ist [basic.types] / 3:
Für jedes Objekt (mit Ausnahme eines Basisklassen-Unterobjekts) vom einfach kopierbaren TypT
, ob das Objekt einen gültigen Wert vom Typ @ enthält oder nicT
, die zugrunde liegenden Bytes [intro.memory]), aus denen das Objekt besteht, kann in ein Array von @ kopiert werdchar
oderunsigned char
. Wenn der Inhalt des Arrays vonchar
oderunsigned char
ird @ wieder in das Objekt kopiert, behält das Objekt anschließend seinen ursprünglichen Wert.Beispiel weggelassen
Die Frage wird dann, ist einmemcpy
Überschreiben einer trivial kopierbaren Klasseninstanz "Copy Construction" oder "Copy Assignment"? Die Antwort auf die Frage scheint zu entscheiden, obMeow_internal
ist eine gültige Möglichkeit für einen Compiler, eine einfach kopierbare Klasse zu implementieren.Meow
.
Wennmemcpy
ist "Kopie Konstruktion", dann ist die Antwort, dassMeow_internal
ist gültig, da die Kopierkonstruktion den Speicher wieder verwendet. Wennmemcpy
ist "Kopierzuweisung", dann lautet die Antwort:Meow_internal
ist keine gültige Implementierung, da durch die Zuweisung keine Zeiger auf die instanziierten Member einer Klasse ungültig werden. Wennmemcpy
ist beides, ich habe keine Ahnung, wie die Antwort lautet.