Чи дозволена арифметика вказівника на виділеному сховищі, оскільки C ++ 20?


10

У стандарті C ++ 20 сказано, що типи масивів - це неявний тип життя .

Чи означає це, що масив до неявного типу життя може бути неявно створений? Неявне створення такого масиву не спричинило б створення елементів масиву?

Розглянемо цей випадок:

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

Цей код вже не є UB, оскільки C ++ 20?


Може, цей спосіб краще?

//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
Я щойно здійснив пошук за (чернетки) стандартом C ++ 20, і не знайшов нічого, що описує масиви як "неявний тип життя" (і, так, я шукав варіанти). Будь ласка, надайте більш детальний опис вашої претензії (наприклад, розділ та пункт у стандарті). Трохи важко відповісти на ваше запитання, не маючи змоги знайти джерело, не кажучи вже про будь-який відповідний контекст.
Петро

1
@Peter: eel.is/c++draft/basic.types#9 , останнє речення
geza

Я переглядав PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf (нібито останній робочий проект), і він навіть не має такого речення. Схоже, вам також знадобиться знайти значення "неявна життя". Я підозрюю, що ваше посилання, можливо, вибрало деякі "редагування в процесі роботи", які навіть не перетворили його на робочі чернетки.
Петро

1
@Peter Зміни є результатом того, що P0593 було об'єднано у стандарт із недавньої зустрічі в Празі. Вони ще не випустили отриману чернетку, але ви можете побачити об'єднане формулювання в цьому комітеті .
волоський горіх

Відповіді:


3

Чи означає це, що масив до неявного типу життя може бути неявно створений?

Так.

Неявне створення такого масиву не спричинило б створення елементів масиву?

Так.

Саме це робить std::vectorреалізованим у звичайному C ++.


Чи можете ви підтвердити, що std::launder(static_cast<std::string*>(ptr))він не повертає вказівник на перший елемент масиву, оскільки він не знаходиться протягом його життя, але std::launder(static_cast<std::string(*)[10]>(ptr))повертає вказівник на масив, тому що масив знаходиться в межах його життя?
Олів

Це мені здається правильним.
ТК

@Oliv І я вважаю, що std::launderнасправді це не потрібно, тому що eel.is/c++draft/intro.object#11 гарантує, що ptrвже вказуватиме на масив?
волоський горіх

@walnut, я це пропустив. Значить, a static_castto std::string (*) [10]має бути достатнім! tx.
Олів

@Oliv Але я здогадуюсь, тоді питання стає чи буде ваш перший приклад без std::launderволі чітко визначений. Немає std::stringоб’єкта, на який слід вказувати, але ptrміг би вказати на масив, так що статичний атрибут залишить значення незмінним і sptrвкаже також на масив. З std::launderним UB просто через std::launderросійські вимоги.
волоський горіх
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.