Справочник по Ada 2005
4.8 Распределители
Вычисление распределителя создаёт объект и возвращает значение доступа, которое указывает на этот объект.
Синтаксис
Правила разрешения имён
Ожидаемый тип для распределителя должен быть типом доступа к объекту с типом назначения D, таким что либо D охватывает тип, определяемый меткой_типа_подтипа индикации типа подтипа, либо квалифицированное_выражение, или ожидаемый тип является анонимным, а определяемый тип является D'Class.
Правила легальности
Инициализированный распределитель — это распределитель с квалифицированным_выражением. Неинициализированный распределитель — это распределитель с индикацией_типа_подтипа. В индикации_типа_подтипа неинициализированного распределителя ограничение разрешается только если метка_типа_подтипа обозначает не ограниченный составной подтип; если ограничения нет, то метка_типа_подтипа должна обозначать определённый подтип.
Если тип распределителя является типом доступа к константе, то распределитель должен быть инициализированным распределителем.
Если тип назначения типа распределителя является широко распространённым классом, уровень доступности типа, определяемого индикацией_типа_подтипа или квалифицированным_выражением, не должен быть статически глубже, чем уровень доступа типа распределителя.
Если подтип назначения типа распределителя имеет один или несколько неограниченных дискриминантов доступа, тогда уровень доступности анонимного типа доступа каждого дискриминанта доступа, как определено индикацией_типа_подтипа или квалифицированным_выражением распределителя, не должен быть статически глубже, чем уровень доступа типа распределителя (см. 3.10.2).
Распределитель не должен быть типа доступа, для которого Storage_Size был задан статическим выражением со значением ноль или определён языком как ноль. В дополнение к местам, где обычно применяются правила легальности (см. 12.3), это правило применяется также в частях `private` экземпляра генерируемого блока. Это правило не применяется в теле генерируемого блока или внутри тела, объявленного в области объявления генерируемого блока, если тип распределителя является потомком формального типа доступа, объявленного в формальной части генерируемого блока.
Статическая семантика
Если тип назначения типа распределителя является элементарным, то подтип созданного объекта является подтипом назначения. Если тип назначения является составным, то подтип созданного объекта является подтипом назначения, когда подтип назначения ограничен или имеется частичный вид ограниченного типа назначения; в противном случае созданный объект ограничен своим начальным значением (даже если подтип назначения неограничен с значениями по умолчанию).
Динамическая семантика
Для вычисления инициализированного распределителя сначала выполняется вычисление квалифицированного_выражения. Создаётся объект типа назначения, и значение квалифицированного_выражения преобразуется в подтип назначения и присваивается объекту.
Для вычисления неинициализированного распределителя сначала выполняется разработка индикации_типа_подтипа. Затем:
- Если тип назначения является элементарным, создаётся объект заданного подтипа, и ему присваивается любое неявное начальное значение;
- Если тип назначения является составным, создаётся объект заданного типа с тэгом, если таковой есть, определённым меткой типа подтипа метки_типа_подтипа индикации_типа_подтипа. Затем этот объект инициализируется по умолчанию (см. 3.3.1), используя индикацию_типа_подтипа для определения его номинального подтипа. Проверяется, что значение объекта принадлежит подтипу назначения. Если эта проверка завершается неудачно, поднимается исключение Constraint_Error. Эта проверка и инициализация объекта выполняются в произвольном порядке.
Для любого распределителя, если тип назначения типа распределителя является широко распространённым классом, проверяется, что уровень доступности типа, определяемый индикацией_типа_подтипа или тэгом значения квалифицированного_выражения, не глубже уровня доступа типа распределителя. Если подтип назначения распределителя имеет один или несколько неограниченных дискриминантов доступа, то проверяется, что уровень доступности анонимного типа доступа каждого дискриминанта доступа не глубже, чем уровень доступа типа распределителя. Если любая такая проверка завершается неудачно, поднимается исключение Program_Error.
Если объект, который должен быть создан распределителем, имеет управляемую или защищённую часть, а завершение сбора типа распределителя (см. 7.6.1) началось, поднимается исключение Program_Error.
Если объект, который должен быть создан распределителем, содержит задачи, и мастер типа распределителя завершён, и все зависимые задачи мастера завершены (см. 9.3), то поднимается исключение Program_Error.
Если создаваемый объект содержит задачи, они активируются (см. 9.2). Наконец, возвращается значение доступа, которое указывает на созданный объект.
Ограниченные ошибки во время выполнения
Ошибка является ограниченной, если завершение сбора типа (7.6.1) распределителя началось. Если ошибка обнаружена, поднимается исключение Program_Error. В противном случае выделение памяти происходит нормально.
ПРИМЕЧАНИЯ
23 Распределители не могут создавать объекты абстрактного типа. См. 3.9.3.
24 Если любая часть создаваемого объекта управляема, инициализация включает вызовы соответствующих процедур Initialize или Adjust. См. 7.6.
25 Как объяснено в 13.11, «Управление памятью», память для объекта, выделенного распределителем, поступает из пула памяти (возможно, пользовательского). Исключение Storage_Error генерируется распределителем, если памяти недостаточно. Экземпляры Unchecked_Deallocation могут использоваться для явного возвращения памяти.
26 Реализации разрешается, но не требуется, обеспечивать сбор мусора (см. 13.11.3).
Примеры
Примеры распределителей:
new Cell'(0, null, null) -- инициализирован явно, см. 3.10.1
new Cell'(Value => 0, Succ => null, Pred => null) -- инициализирован явно
new Cell -- не инициализирован
new Cell'(Value => 0, Succ => null, Pred => null) -- инициализирован явно
new Cell -- не инициализирован
new Matrix(1 .. 10, 1 .. 20) -- указаны только границы
new Matrix'(1 .. 10 => (1 .. 20 => 0.0)) -- явно инициализирован
new Matrix'(1 .. 10 => (1 .. 20 => 0.0)) -- явно инициализирован
new Buffer(100) -- указан только дискриминант
new Buffer'(Size => 80, Pos => 0, Value => (1 .. 80 => 'A')) -- явно инициализирован
new Buffer'(Size => 80, Pos => 0, Value => (1 .. 80 => 'A')) -- явно инициализирован
Expr_Ptr'(new Literal) -- аллокатор для доступа к типу, общий для класса, см. 3.9.1
Expr_Ptr'(new Literal'(Expression с 3.5)) -- явно инициализирован
Expr_Ptr'(new Literal'(Expression с 3.5)) -- явно инициализирован