2016-11-15 5 views
5

Я новичок в Ada.Ada out параметр

Я видел этот question, но мой немного отличается:

type A is record 
     x : integer; 
     y : integer; 
    end record; 

    procedure P1 is 
     temp : A; 
    begin 
     temp.x := 100; 
     P2(temp); 
     if temp.x = 100 then 
     Ada.Text_IO.Put_Line("true"); 
     else 
     Ada.Text_IO.Put_Line("false"); 
     end if; 
    end One; 

    procedure P2 (arg1 : out A) is 
    begin 
     arg1.y := 200; 
    end P2; 

Мой вопрос с «из» параметра P2: будут другие части составного типа неопределен, если P2 не явно установите их. Другими словами, если вызывается P1, будет ли вывод определенно истинным или ложным? Или, может быть, двусмысленный?

Этот link говорит о «инициализации по умолчанию», но мой пример выше не имеет его явно (специально).

Safety is preserved by ensuring that a subcomponent does not become 
    "deinitialized" by being passed as an out parameter. If any subcomponent 
    of a type passed by copy has default initialization, then the whole 
    object is copied in at the start of the call so that the value of such a 
    subcomponent is not lost as a result of a subprogram call during which 
    no assignment is made to the subcomponent. But in practice records are 
    usually passed by reference anyway. 

ответ

6

Котировочная проход, §6.1.1 Out Parameters, может быть легче понять после рассмотрения §6.2 Formal Parameter Modes. Для параметра типа A «не указано, передан ли параметр копией или по ссылке». Реализация свободна в выборе. В любом случае компонент x значения типа A не изменяется на P2. P1 печатает «true», потому что вы дали x компоненту значение 100 явно до звонка P2. При отсутствии инициализации, по умолчанию или в противном случае temp.x содержит любые биты в памяти при создании места для temp, как правило, путем корректировки указателя стека.

В качестве упражнения, попробуйте опустить инициализацию и исследования значения:

--temp.x := 100; 
P2(temp); 
if temp.x = 100 then 
    Ada.Text_IO.Put_Line("true"); 
else 
    Ada.Text_IO.Put_Line("false"); 
end if; 
Ada.Text_IO.Put_Line(temp.x'Img & temp.y'Img); 

В моей реализации, предикат терпит неудачу и temp.x содержит мусор.

false 
1934820168 200 

Использование default_expression с записью компонентов позволяет избежать риска с видом на инициализацию.

type A is record 
    x : integer := 0; 
    y : integer := 0; 
end record; 

Если компилятор зависимы, то использует in out единственный верный способ убедиться, что он работает.

Отсутствует инициализация по умолчанию, да. Как отмечалось в §6.1 Parameter and Result Mechanism, «В Ada 95 не erroneous зависеть от параметра прохождения механизма (по ссылке против по-копии) для тех типов, которые позволяют одновременно, хотя это непереносимой.» Поскольку arg1 в P2 является out параметром, который может быть передана копии й она не является ни типом доступа, ни составной типа с дискриминантами, ни типа, имеющий неявное начальное значение- §6.4.1 Parameter Associations делает очевидными, что «формальный параметр неинициализированный. " Напротив, для параметра in out «значение фактического параметра ... присвоено формальным».

+1

Я не уверен, является ли это специфичным для компилятора поведение? Будет ли компилятор, который мог бы пройти по копии, будет вести себя так же?Я постараюсь не рисковать! –

+0

Спасибо @trashgod. Если он зависит от компилятора, то использует «in out» единственный верный способ убедиться, что он работает (если вы не уверены, что прошедшая запись имеет инициализацию по умолчанию): 'procedure P2 (arg1: in out A) is ' ' begin' 'arg1.y: = 200;' 'end P2;' –

+1

@TNguyen: Я разработал выше. – trashgod

Смежные вопросы