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");
Odpowiedzi:
Tak.
Tak.
To sprawia, że można go
std::vector
wdrożyć w zwykłym C ++.źródło
std::launder(static_cast<std::string*>(ptr))
nie zwraca wskaźnika do pierwszego elementu tablicy, ponieważ nie znajduje się on w okresie jego istnienia, alestd::launder(static_cast<std::string(*)[10]>(ptr))
zwraca wskaźnik do tablicy, ponieważ tablica jest w trakcie jej życia?std::launder
tak naprawdę nie jest potrzebne, ponieważ eel.is/c++draft/intro.object#11 gwarantuje, żeptr
już wskaże tablicę?static_cast
abystd::string (*) [10]
powinno wystarczyć! tx.std::launder
będzie dobrze zdefiniowany. Nie mastd::string
obiektu, na któryptr
mógłby wskazywać , ale mógłby wskazywać na tablicę, więc rzut statyczny pozostawi wartość bez zmian isptr
wskaże również tablicę. Dziękistd::launder
temu UB jest po prostu ze względu nastd::launder
wymagania.