Spec-Zone.ru › Ada 2022
Справочник по Ada (Ada 2022)

7.6 Присваивание и завершение

Три вида действий являются основополагающими для работы с объектами: инициализация, завершение и присваивание. Каждый объект инициализируется, явно или по умолчанию, после создания (например, с помощью object_declaration или allocator). Каждый объект завершается перед уничтожением (например, при выходе из subprogram_body, содержащего object_declaration, или при вызове Unchecked_Deallocation). Операция присваивания используется в assignment_statements, явной инициализации, передаче параметров и других операциях.
Язык предоставляет определения по умолчанию для этих трех фундаментальных операций, но управляемый тип дает пользователю дополнительный контроль над частями этих операций. В частности, пользователь может определить для управляемого типа процедуру Initialize, которая вызывается сразу после обычной инициализации по умолчанию управляемого объекта, процедуру Finalize, которая вызывается непосредственно перед завершением любых компонентов управляемого объекта, и процедуру Adjust, которая вызывается в последнюю очередь при присваивании (не ограниченному) управляемому объекту.

Статическая семантика

Существует следующий определённый языком пакет библиотеки:
package Ada.Finalization
with Pure, Nonblocking => False is
type Controlled is abstract tagged private
with Preelaborable_Initialization;
procedure Initialize (Object : in out Controlled) is null;
procedure Adjust (Object : in out Controlled) is null;
procedure Finalize (Object : in out Controlled) is null;
type Limited_Controlled is abstract tagged limited private
with Preelaborable_Initialization;
procedure Initialize (Object : in out Limited_Controlled) is null;
procedure Finalize (Object : in out Limited_Controlled) is null;
private
... -- не определено языком
end Ada.Finalization;
Управляемый тип является потомком Controlled или Limited_Controlled. Предопределённый оператор "=" типа Controlled всегда возвращает True, так как этот оператор встроен в реализацию предопределённого оператора равенства для типов, полученных из Controlled, как объяснено в 4.5.2. Тип Limited_Controlled похож на Controlled, за исключением того, что он ограничен и лишен примитивной подпрограммы Adjust.
Говорят, что тип требует завершения, если:
  • это управляемый тип, тип задачи или защищённый тип; или
  • он имеет компонент, тип которого требует завершения; или
  • это тип всего класса; или
  • это частичный вид, у которого полный вид требует завершения; или
  • это один из нескольких определённых языком типов, которые явно определены как требующие завершения.

Динамическая семантика

Во время разработки или вычисления конструкции, которая приводит к инициализации объекта по умолчанию, для каждого управляемого подкомпонента объекта, которому не присвоено начальное значение (как определено в 3.3.1), вызывается Initialize для этого подкомпонента. Аналогично, если объект, который инициализируется по умолчанию в целом, управляемый, то вызывается Initialize для объекта.
Для extension_aggregate, у которого ancestor_part является subtype_mark, обозначающей управляемый подтип, вызывается процедура Initialize предкового типа, если эта процедура не абстрактная.
Initialize и другие операции инициализации выполняются в произвольном порядке, за исключением следующего. Initialize применяется к объекту после инициализации его подкомпонентов, если таковые имеются (включая неявную инициализацию и вызовы Initialize). Если объект имеет компонент с дискриминантом доступа, ограниченным выражением для каждого объекта, Initialize применяется к этому компоненту после любых компонентов, у которых нет таких дискриминантов. Для объекта с несколькими компонентами с таким дискриминантом Initialize применяется к ним в порядке их component_declarations. Для allocator, любые активации задач следуют за всеми вызовами Initialize.
При присваивании целевому объекту со всеми управляемыми частями значения, либо при создании, либо в последующем assignment_statement, операция присваивания выполняется следующим образом:
  • Значение целевого объекта становится присвоенным значением.
  • Значение целевого объекта корректируется.
Для корректировки значения составного объекта сначала значения компонентов объекта корректируются в произвольном порядке, а затем, если объект не ограничен и управляем, вызывается Adjust. Корректировка значения элементарного объекта не оказывает влияния, так же как и корректировка значения составного объекта без управляемых частей.
Для assignment_statement, после того, как name и expression были оценены и выполнено любое преобразование (включая проверку ограничений), создаётся анонимный объект, и значение присваивается в него; то есть, применяется операция присваивания. (Присваивание включает корректировку значения.) Затем целевой объект assignment_statement завершается. Затем значение анонимного объекта присваивается в цель assignment_statement. Наконец, анонимный объект завершается. Как объяснено ниже, реализация может исключить промежуточный анонимный объект, поэтому это описание включает то, что дано в 5.2, «Операции присваивания».
Когда вызов функции или aggregate используется для инициализации объекта, результат вызова функции или aggregate является анонимным объектом, который присваивается вновь созданному объекту. Для такого присваивания анонимный объект может быть построен на месте, в этом случае присваивание не включает копирование. В определённых обстоятельствах анонимный объект должен быть построен на месте. В частности:
  • Если полный тип любой части объекта неизменно ограничен, анонимный объект строится на месте.
  • В случае aggregate, если полный тип любой части вновь созданного объекта управляем, анонимный объект строится на месте.
  • В других случаях не определено, строится ли анонимный объект на месте.
Несмотря на то, что этот документ говорит в других местах, если объект построен на месте:
  • По завершении возврата или aggregate, анонимный объект превращается в вновь созданный объект; то есть, анонимный объект перестаёт существовать, а вновь созданный объект появляется на его месте.
  • Завершение не выполняется для анонимного объекта.
  • Корректировка не выполняется для вновь созданного объекта.
  • Все значения доступа, обозначающие части анонимного объекта, теперь обозначают соответствующие части вновь созданного объекта.
  • Все переименования частей анонимного объекта теперь обозначают представления соответствующих частей вновь созданного объекта.
  • Совместные расширения анонимного объекта становятся совместными расширениями вновь созданного объекта.

Разрешения реализации

Реализация имеет право смягчить вышеуказанные правила для assignment_statements следующим образом:
  • Если объекту присваивается значение этого же объекта, реализация может пропустить всё присваивание.
  • Для присваивания типа без управления реализация может завершить и присвоить каждый компонент переменной по отдельности (а не завершить всю переменную и присвоить всё новое значение), если дискриминанта переменной не изменяется при присваивании.
  • Реализация может избежать создания анонимного объекта, если присваиваемое значение является результатом оценки name, обозначающего объект (исходный объект), чья память не может перекрываться с целевой. Если исходный объект может перекрываться с целевым объектом, то реализация может избежать необходимости промежуточного анонимного объекта, используя одно из вышеупомянутых разрешений и выполнить присваивание по одному компоненту за раз (для перекрывающегося присваивания массива) или вообще не выполнять (для присваивания, где целевой и исходный объекты присваивания являются одним и тем же объектом).
Кроме того, реализация разрешается пропускать неявные вызовы Initialize, Adjust и Finalize и связанные с ними операции присваивания для объекта не ограниченного управляемого типа при условии, что:
  • любой пропущенный вызов Initialize не является вызовом пользовательской процедуры Initialize, и
  • любое использование значения объекта после неявного вызова Initialize или Adjust и перед последующим вызовом Finalize для объекта не изменяет внешнего эффекта программы, и
  • после исключения таких вызовов и операций, любое выполнение программы, которое выполняет вызов Initialize или Adjust для объекта или инициализирует объект с помощью агрегата, также позже выполнит вызов Finalize для объекта и всегда сделает это до присвоения нового значения объекту, и
  • операции присваивания, связанные с пропущенными вызовами Adjust, также пропускаются.
Это разрешение распространяется на вызовы Adjust и Finalize, даже если неявные вызовы имеют дополнительные внешние эффекты.


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API