Czy arytmetyka wskaźnika na przydzielonej pamięci jest dozwolona od C ++ 20?

10

W standardzie C ++ 20 mówi się, że typy tablic są domyślnymi typami życia .

Czy to oznacza, że ​​tablica dla niejawnego typu życia może być niejawnie utworzona? Domniemane utworzenie takiej tablicy nie spowodowałoby utworzenia elementów tablicy?

Rozważ ten przypadek:

//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");

Czy ten kod nie jest już UB od C ++ 20?


Może ten sposób jest lepszy?

//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");
Oliv
źródło
1
Właśnie przeszukałem (szkic) standard C ++ 20 i nie znalazłem niczego, co opisywałoby tablice jako „domyślny typ życia” (i tak, szukałem odmian). Proszę podać bardziej szczegółowy opis roszczenia (np. Sekcja i klauzula w standardzie). Trudno odpowiedzieć na twoje pytanie, nie będąc w stanie znaleźć źródła, nie mówiąc już o jakimkolwiek odpowiednim kontekście.
Peter
1
@Peter: eel.is/c++draft/basic.types#9 , ostatnie zdanie
geza
Patrzyłem na plik PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf (pozornie najnowszy działający projekt) i nie ma nawet tego zdania. Wygląda na to, że musisz także znaleźć znaczenie „niejawnego życia”. Podejrzewam, że Twój link mógł wykryć pewne „zmiany w toku”, które nawet nie przeszły do ​​wersji roboczej.
Peter
1
@Peter Zmiany są wynikiem połączenia P0593 ze standardem z ostatniego spotkania w Pradze. Nie wydali jeszcze wynikowej wersji roboczej, ale można zobaczyć scalone sformułowania w tym zatwierdzeniu .
orzech

Odpowiedzi:

3

Czy to oznacza, że ​​tablica dla niejawnego typu życia może być niejawnie utworzona?

Tak.

Domniemane utworzenie takiej tablicy nie spowodowałoby utworzenia elementów tablicy?

Tak.

To sprawia, że ​​można go std::vectorwdrożyć w zwykłym C ++.

TC
źródło
Czy możesz również potwierdzić, że std::launder(static_cast<std::string*>(ptr))nie zwraca wskaźnika do pierwszego elementu tablicy, ponieważ nie znajduje się on w okresie jego istnienia, ale std::launder(static_cast<std::string(*)[10]>(ptr))zwraca wskaźnik do tablicy, ponieważ tablica jest w trakcie jej życia?
Oliv
To wydaje mi się poprawne.
TC
@Oliv I przypuszczam, że std::laundertak naprawdę nie jest potrzebne, ponieważ eel.is/c++draft/intro.object#11 gwarantuje, że ptrjuż wskaże tablicę?
orzech
@walnut, tęskniłem za tym. Tak static_castaby std::string (*) [10]powinno wystarczyć! tx.
Oliv
@Oliv Ale wydaje mi się, że pytanie brzmi wtedy, czy twój pierwszy przykład bez std::launderbędzie dobrze zdefiniowany. Nie ma std::stringobiektu, na który ptrmógłby wskazywać , ale mógłby wskazywać na tablicę, więc rzut statyczny pozostawi wartość bez zmian i sptrwskaże również tablicę. Dzięki std::laundertemu UB jest po prostu ze względu na std::launderwymagania.
orzech