Discussion:
Retour de fonction d'un type contrôlé.
(trop ancien pour répondre)
Blady
2021-02-21 20:40:23 UTC
Permalink
Bonjour,

Soit un type contrôlé et une fonction qui retourne ce type, parmi les
trois fonctions suivantes avec trois formes de retour :
- agrégat
- variable locale
- instruction return étendue
quelle est la forme qui serait meilleure du point de vue du nombre de
copie en mémoire et donc du nombre d'appels à Adjust et Finalize ?

type My_Type is new Ada.Finalization.Controlled with record
A1 : String (1 .. 10);
A2 : Boolean;
A3 : Float;
end record;

function F1 (V : Float) return My_Type is
-- agrégat
begin
return (Ada.Finalization.Controlled with "0123456789", V > 0.0, V
/ 2.0);
end F1;

function F2 (V : Float) return My_Type is
-- variable locale
L : My_Type;
begin
L.A1 := "0123456789";
L.A2 := V > 0.0;
L.A3 := V / 2.0;
return L;
end F2;

function F3 (V : Float) return My_Type is
-- instruction return étendue
begin
return L : My_Type do
L.A1 := "0123456789";
L.A2 := V > 0.0;
L.A3 := V / 2.0;
end return;
end F3;

Merci pour vos réponses, Pascal.
J-P. Rosen
2021-02-22 06:53:43 UTC
Permalink
Post by Blady
Soit un type contrôlé et une fonction qui retourne ce type, parmi les
    - agrégat
    - variable locale
    - instruction return étendue
quelle est la forme qui serait meilleure du point de vue du nombre de
copie en mémoire et donc du nombre d'appels à Adjust et Finalize ?
Une seule réponse: fais l'essai.

Le modèle formel implique pas mal de copies (pour être sûr que la
sémantique est préservée), mais il est prévu que le compilateur en
optimise un certain nombre, en particulier dans les cas simples et les
plus fréquents. Donc, faut voir ce que fait le compilo...
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
Blady
2021-02-28 10:59:49 UTC
Permalink
Post by J-P. Rosen
Post by Blady
Soit un type contrôlé et une fonction qui retourne ce type, parmi les
     - agrégat
     - variable locale
     - instruction return étendue
quelle est la forme qui serait meilleure du point de vue du nombre de
copie en mémoire et donc du nombre d'appels à Adjust et Finalize ?
Une seule réponse: fais l'essai.
Le modèle formel implique pas mal de copies (pour être sûr que la
sémantique est préservée), mais il est prévu que le compilateur en
optimise un certain nombre, en particulier dans les cas simples et les
plus fréquents. Donc, faut voir ce que fait le compilo...
Après essai avec GNAT Community 2020, les trois formes sont identiques
quant au nombre d'Ajust et de Finalize, seul Initialize n'est pas appelé
avec la forme agrégat (ce qui était prévisible).

Je m'attendais à ce qu'avec la forme agrégat que celui-ci soit
directement construit dans le retour de fonction ce qui aurait évité un
Adjust et un Finalize mais ce n'est pas apparemment le cas avec GNAT.

Pascal.

PS : mon programme de test :

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Finalization;

procedure Test_20210228_ret_fin is

type My_Type is new Ada.Finalization.Controlled with record
A1 : String (1 .. 10);
A2 : Boolean;
A3 : Float;
A4 : Integer := 5; -- Témoin
end record;

procedure Initialize (O : in out My_Type);
procedure Adjust (O : in out My_Type);
procedure Finalize (O : in out My_Type);

procedure Initialize (O : in out My_Type) is
begin
O.A4 := O.A4 + 10;
Put_Line ("Initialize : " & O.A4'Image);
end Initialize;

procedure Adjust (O : in out My_Type) is
begin
O.A4 := O.A4 + 100;
Put_Line ("Adjust : " & O.A4'Image);
end Adjust;

procedure Finalize (O : in out My_Type) is
begin
O.A4 := O.A4 + 1_000;
Put_Line ("Finalize : " & O.A4'Image);
end Finalize;

function F1 (V : Float) return My_Type is
-- agrégat
begin
return (Ada.Finalization.Controlled with "0123456789", V > 0.0, V
/ 2.0, 1);
end F1;

function F2 (V : Float) return My_Type is
-- variable locale
L : My_Type;
begin
L.A1 := "0123456789";
L.A2 := V > 0.0;
L.A3 := V / 2.0;
L.A4 := 2;
return L;
end F2;

function F3 (V : Float) return My_Type is
-- instruction return étendue
begin
return L : My_Type do
L.A1 := "0123456789";
L.A2 := V > 0.0;
L.A3 := V / 2.0;
L.A4 := 3;
end return;
end F3;

X : My_Type;

begin
Put_Line ("Before F1 call : " & X.A4'Image);
X := F1 (1.0);
Put_Line ("After F1 call : " & X.A4'Image);
Put_Line ("Before F2 call : " & X.A4'Image);
X := F2 (2.0);
Put_Line ("After F2 call : " & X.A4'Image);
Put_Line ("Before F3 call : " & X.A4'Image);
X := F3 (3.0);
Put_Line ("After F3 call : " & X.A4'Image);
end Test_20210228_ret_fin;

L'exécution :
-- Initialize : 15 -> init X
-- Before F1 call : 15
-- Adjust : 101 -> copy aggregate -> function return
-- Finalize : 1001 -> finalize aggregate
-- Finalize : 1015 -> finalize X
-- Adjust : 201 -> copy function return -> X
-- Finalize : 1101 -> finalize function return
-- After F1 call : 201
-- Before F2 call : 201
-- Initialize : 15 -> init local L
-- Adjust : 102 -> copy local L -> function return
-- Finalize : 1002 -> finalize local L
-- Finalize : 1201 -> finalize X
-- Adjust : 202 -> copy function return -> X
-- Finalize : 1102 -> finalize function return
-- After F2 call : 202
-- Before F3 call : 202
-- Initialize : 15 -> init local L
-- Adjust : 103 -> copy local L -> function return
-- Finalize : 1003 -> finalize local L
-- Finalize : 1202 -> finalize X
-- Adjust : 203 -> copy function return -> X
-- Finalize : 1103 -> finalize function return
-- After F3 call : 203
-- Finalize : 1203 -> finalize X

Loading...