Время жизни объекта, который имеет пустую инициализацию - PullRequest
0 голосов
/ 03 сентября 2018

В текущем проекте стандарта (прежние стандарты имеют аналогичную формулировку) в [basic.life/1] :

Время жизни объекта или ссылки является свойством времени выполнения объект или ссылка. Говорят, что объект имеет не пустую инициализация, если он принадлежит к классу или агрегатному типу, и он или один из его подобъекты инициализируются конструктором, отличным от тривиального конструктор по умолчанию. [Примечание: инициализация с помощью тривиального копирования / перемещения Конструктор не пустая инициализация. - конец примечания] Время жизни объекта типа T начинается, когда:

(1.1) хранение с надлежащим выравнивание и размер для типа T получается, и

(1.2), если объект имеет не пустая инициализация, ее инициализация завершена,

См. Этот код:

alignas(int) char obj[sizeof(int)];

Означает ли basic.life/1, что здесь int (и несколько других типов, которые имеют те же или меньшие требования к выравниванию / размеру, что и int), начал свою жизнь?

Что это вообще значит? Если объект начал свою жизнь, он создан? [intro.object / 1] говорит:

[...] Объект создается по определению ([basic.def]), выражению new, при неявном изменении активного члена объединения ([class.union]) или при временном объект создан ([conv.rval], [class.teven]) [...]

Итак, согласно этому мой obj (как int) не создан. Но его время жизни как int (и, как и у других, возможно, вакуумно-инициализируемых объектов бесконечного типа) началось.

Я в замешательстве, вы можете дать разъяснение по этому поводу?

Ответы [ 3 ]

0 голосов
/ 03 сентября 2018

Вы не можете начать время жизни объекта, если объект не был создан . И [intro.object] / 1 определяет единственные способы создания объектов:

Объект создается по определению (6.1), новым выражением (8.3.4), при неявном изменении активного члена объединения (12.3) или при создании временного объекта (7.4, 15.2) .

Объект, созданный по этому определению, имеет тип char[]. Следовательно, это единственный объект, чье время жизни начинается. И никакие другие объекты не создаются этой конструкцией.

Для подтверждения этой интерпретации существует предложение для C ++ 20 P0593 , основная цель которого состоит в том, чтобы разрешить этой самой декларации неявно создавать другие подобные объекты.


Комментарии:

Условие в (1.2) все еще беспокоит меня. Почему это там?

Он существует потому, что не может сказать "инициализация завершена" для объекта, который не подвергается инициализации.

предположим, что у меня потом new(obj) int. Это явно создает объект int. Но до этого obj получил необходимое хранилище.

Нет, объявление obj получило хранилище для объекта типа char[]. Что получает хранилище для создаваемого объекта int, это new(obj). Да, выражение place-new получает хранилище для создаваемого объекта. Так же, как объявление переменной получает хранилище для объекта, который она создает.

То, что хранилище уже существует, не означает, что оно не получено.

0 голосов
/ 04 сентября 2018

Поскольку стандарт намеренно воздерживается от требования, чтобы все реализации были пригодны для всех целей, часто для качественных реализаций, предназначенных для различных целей, часто требуется гарантировать поведение кода, к которому сам стандарт не предъявляет никаких требований.

Если некоторый тип T поддерживает создание неявных объектов и программа преобразует адрес некоторого объекта в T*, высококачественная реализация, предназначенная для поддержки концепций низкоуровневого программирования без использования специального синтаксиса, будет вести себя как хотя такое преобразование создает объект типа T в тех случаях, когда это позволило бы программе иметь определенное поведение, но не могло бы неявно создавать такие объекты, в случаях, когда это не было бы необходимо, но вместо этого приводило бы к неопределенному поведению путем уничтожения других объекты.

Таким образом, если float и uint32_t имеют одинаковый размер и имеют одинаковые требования к выравниванию, то, например,

alignas(uint32_t) char obj[sizeof(uint32_t)];

float *fp = (float*)obj;
*fp = 1.0f;
uint32_t *up = (uint32_t*)obj;

Инициализация fp создаст float, потому что это потребуется для выполнения назначения *fp. Если up будет использоваться таким образом, что для его существования требуется uint32_t, присвоение up может создать его при уничтожении float, который был там. Если up не используется таким образом, но fp используется таким образом, что требуется, чтобы float все еще существовал, то float все еще существовал бы. Если оба указателя используются способами, которые потребуют, чтобы соответствующие объекты все еще существовали, даже качественный компилятор, предназначенный для низкоуровневого программирования, мог бы не справиться с такой возможностью.

Обратите внимание, что реализации, которые не особенно подходят для низкоуровневого программирования, могут не поддерживать семантику, описанную здесь. Авторы Стандарта позволяют авторам компиляторов поддерживать такую ​​семантику или нет, основываясь на том, необходимы ли они для предполагаемых целей их компиляторов; к сожалению, пока нет никакого стандартного способа отличить компиляторы, которые подходят для таких целей, от тех, которые не подходят.

0 голосов
/ 03 сентября 2018

Я интерпретирую

Время жизни объекта типа T начинается, когда ...

означает

Учитывая, что программа создает объект T, следующее описывает, когда говорят, что время жизни этого объекта начинается ...

а не

Если выполняются следующие условия, тогда существует объект типа T, и его время жизни начинается, когда ...

То есть существует неявное дополнительное условие, что объект «создается» некоторым образом, описанным в [intro.object] / 1. Но параграф [basic.life] 1 / не означает, что сам по себе подразумевает, что какой-либо объект существует, только одно из свойств объектов, которые существуют.

Таким образом, для вашего объявления в тексте описывается начало времени жизни одного объекта типа char[sizeof(int)] и одного или нескольких объектов типа char (даже если объявление является оператором в области видимости блока и отсутствует инициализации), но поскольку нет объекта типа int, подразумеваемого для существования, мы не будем ничего говорить о времени жизни такого объекта.

...