Ist Zeigerarithmetik für zugewiesenen Speicher seit C ++ 20 zulässig?


10

Im C ++ 20-Standard wird gesagt, dass Array-Typen implizite Lebensdauertypen sind .

Bedeutet dies, dass ein Array für einen nicht impliziten Lebensdauertyp implizit erstellt werden kann? Die implizite Erstellung eines solchen Arrays würde nicht zur Erstellung der Elemente des Arrays führen.

Betrachten Sie diesen Fall:

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");

Ist dieser Code seit C ++ 20 nicht mehr UB?


Vielleicht ist dieser Weg besser?

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to the array of 10 std::string" 
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");

1
Ich habe gerade den (Entwurfs-) C ++ 20-Standard durchsucht und nichts gefunden, was Arrays als "impliziten Lebensdauertyp" beschreibt (und ja, ich habe nach Variationen gesucht). Bitte geben Sie eine detailliertere Beschreibung Ihres Anspruchs an (z. B. Abschnitt und Klausel in der Norm). Es ist etwas schwierig, Ihre Frage zu beantworten, ohne die Quelle zu finden, geschweige denn einen relevanten Kontext.
Peter

1
@Peter: eel.is/c++draft/basic.types#9 , letzter Satz
Geza

Ich habe mir das PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf (angeblich den neuesten Arbeitsentwurf) angesehen und es enthält nicht einmal diesen Satz. Sieht so aus, als müssten Sie auch die Bedeutung von "impliziter Lebensdauer" finden. Ich vermute, Ihr Link hat möglicherweise einige "laufende Änderungen" aufgegriffen, die es noch nicht einmal in veröffentlichte Arbeitsentwürfe geschafft haben.
Peter

1
@Peter Die Änderungen sind das Ergebnis der Zusammenführung von P0593 mit dem Standard des letzten Prager Treffens. Sie haben den resultierenden Entwurf noch nicht veröffentlicht, aber Sie können den zusammengeführten Wortlaut in diesem Commit sehen .
Walnuss

Antworten:


3

Bedeutet dies, dass ein Array für einen nicht impliziten Lebensdauertyp implizit erstellt werden kann?

Ja.

Die implizite Erstellung eines solchen Arrays würde nicht zur Erstellung der Elemente des Arrays führen.

Ja.

Dies macht die std::vectorImplementierung in normalem C ++ möglich.


Können Sie auch bestätigen, dass std::launder(static_cast<std::string*>(ptr))kein Zeiger auf das erste Element des Arrays zurückgegeben wird, weil es sich nicht innerhalb seiner Lebensdauer befindet, sondern dass std::launder(static_cast<std::string(*)[10]>(ptr))ein Zeiger auf das Array zurückgegeben wird, weil sich das Array innerhalb seiner Lebensdauer befindet?
Oliv

Das scheint mir richtig zu sein.
TC

@Oliv Und ich nehme an, das std::launderwird eigentlich nicht benötigt, weil eel.is/c++draft/intro.object#11 garantiert, dass ptres bereits auf das Array verweist ?
Walnuss

@walnut, das habe ich verpasst. Ein static_castto std::string (*) [10]sollte also ausreichen! tx.
Oliv

@Oliv Aber ich denke die Frage wird dann, ob dein erstes Beispiel ohne das std::laundergut definiert sein wird. Es gibt kein std::stringObjekt, auf das gezeigt werden kann, das jedoch ptrauf das Array verweisen könnte, sodass die statische Umwandlung den Wert unverändert lässt und sptrauch auf das Array zeigt. Damit std::launderist UB einfach wegen der std::launderAnforderungen.
Walnuss
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.