Nicht spezifizierte implizite Objekterstellung

9

Da P0593 die implizite Erstellung von Objekten für die Objektmanipulation auf niedriger Ebene akzeptiert wurde, können Objekte jetzt implizit in C ++ 20 erstellt werden.

Insbesondere ermöglicht der durch den Vorschlag eingeführte Wortlaut, dass bestimmte Vorgänge (z. B. std::malloc) automatisch die Lebensdauer von Objekten bestimmter Typen, sogenannte implizite Lebensdauer-Typen , erstellen und starten , wenn die Einführung solcher Objekte dazu führen würde, dass ein Programm mit ansonsten undefiniertem Verhalten vorliegt definiertes Verhalten. Siehe [intro.object] / 10 .

Der Entwurf besagt nun weiter, dass, wenn es mehrere Sätze solcher Objekte gibt, die implizit erstellt werden könnten, um dem Programm ein definiertes Verhalten zu verleihen, nicht angegeben ist, welcher dieser Sätze erstellt wird. (Der relevante Satz scheint in der letzten Überarbeitung des Vorschlags, auf die ich zugreifen konnte, R5, nicht vorhanden zu sein, befindet sich jedoch im Entwurf des Commits.)

Gibt es tatsächlich ein Programm, für das diese Auswahl implizit erstellter Objektmengen beobachtbar ist? Mit anderen Worten, gibt es ein Programm mit definiertem, aber nicht spezifiziertem Verhalten durch diese neue Regel, so dass aus der Ausgabe geschlossen werden kann, welche Arten von impliziten Objekttypen (aus mehr als einem möglichen) erstellt wurden?

Oder sollte dieser Satz lediglich die Programmausführung auf der abstrakten Maschine verdeutlichen (ohne beobachtbare Auswirkungen)?

Nussbaum
quelle
2
(OT) Wenn ein implizit erstelltes Objekt ein int ist, können wir es "implizites int" nennen?
MM
Es scheint unklar, ob die Wahl des Elements aus der nicht spezifizierten Menge zum Zeitpunkt des
MM
@MM Ich ging davon aus, dass die Auswahl der Menge abstrakt als eine einzige Auswahl für die gesamte Programmausführung außerhalb des Ausführungsflusses betrachtet wurde, wobei die Erstellung jedoch direkt bei der betreffenden Operation (dh std::malloc) erfolgt, da sonst Probleme mit der Definition auftreten rekursiv abhängig von der Zukunft.
Walnuss
Ich habe eine weitere Frage zu diesem Thema gestellt: stackoverflow.com/questions/60627249 . Natürlich fallen mir noch einige Folgerungen ein, aber jeweils eine Frage.
MM
Der Vorschlag behauptet, dass es unmöglich ist, so zu unterscheiden, was wichtig ist, da es keine Möglichkeit gibt, die Wahl „richtig“ zu treffen, sondern nur Optimierungen, um dies zu vermeiden, wären ( sehr streng) gültig.
Davis Herring

Antworten:

9

Nehmen wir das Beispiel im Standard und ändern es ein wenig:

#include <cstdlib>
struct X { int a, b; };
X *make_x() {
  // The call to std::malloc implicitly creates an object of type X
  // and its subobjects a and b, and returns a pointer to that X object
  // (or an object that is pointer-interconvertible ([basic.compound]) with it),
  // in order to give the subsequent class member access operations
  // defined behavior.
  X *p = (X*)std::malloc(sizeof(struct X) * 2); // me: added the *2
  p->a = 1;
  p->b = 2;
  return p;
}

Bisher gab es nur einen Satz gültiger Objekte, die implizit in diesem Speicher erstellt werden konnten - es musste genau eines sein X. Aber jetzt haben wir Speicherplatz für zwei XSekunden, schreiben aber nur auf einen von ihnen, und nichts in diesem Programm berührt jemals den Rest der Bytes. Es gibt also viele verschiedene Arten von Objekten, die implizit erstellt werden könnten - vielleicht zwei X, vielleicht ein Xund zwei int, vielleicht ein Xund acht char, ...

Es ist nicht beobachtbar, welche Menge erstellt wird, denn wenn es tatsächlich Beobachtungen gäbe, würde dies die Möglichkeiten auf nur die Mengen reduzieren, die gültig waren. Wenn wir so etwas gemacht haben, p[1]->a = 3dann kollabiert das Universum der Möglichkeiten auf das mit zwei Xs.

Mit anderen Worten, mehrere Sätze implizit erstellter Objekte sind möglicherweise nur dann vorhanden, wenn das Programm nicht genügend Beobachtungen enthält, um ihre Gültigkeit zu unterscheiden. Wenn es eine Möglichkeit gäbe, zu unterscheiden, wären sie per Definition nicht alle gültig.

Barry
quelle
Dies ist sowieso nur meine Vermutung.
Barry
Ich gehe davon aus, dass es einfach keine Möglichkeit gibt, die Existenz oder Nichtexistenz von Objekten verschiedener impliziter Lebensdauertypen ohne undefiniertes Verhalten zu unterscheiden / zu beobachten. In diesem Fall scheint es mir, dass es die einzige Verwendung von " nicht spezifiziertem Verhalten " im Standard ist, die nicht tatsächlich zu unterschiedlichen beobachtbaren Ergebnissen führen kann.
Walnuss
1
Oder was , wenn die nur Zugriffe über glvalues vom Typ sind [cv] char, unsigned charoder std::byte? Dort könnte auch ein Objekt eines trivial kopierbaren Typs existieren, denke ich?
Aschepler
2
Selbst im ursprünglichen Beispiel ist es auch möglich, ein Array-Objekt zusammen mit dem einen XObjekt zu erstellen .
TC