例如:
type PERSONCV is
record
name: String ( 1..4 );
age: Integer;
cvtext: String ( 1..2000 );
end record;
N: constant := 40000;
persons : array ( 1..N ) of PERSONCV;
function jobcandidate return Boolean is
iscandidate: Boolean := False;
begin
for p of persons loop -- what code is generated for this?
if p.age >= 18 then
iscandidate := true;
exit;
end if;
end loop;
return iscandidate;
end;
Run Code Online (Sandbox Code Playgroud)
在C/C++中,循环部分通常是:
PERSONCV * p; // address pointer
int k = 0;
while ( k < N )
{
p = &persons [ k ]; // pointer to k'th record
if ( p->age >= 18 )...
...
k++ ;
}
Run Code Online (Sandbox Code Playgroud)
我读过Ada对记录使用Value语义.上面的Ada循环是否将第k个记录复制到循环变量p?例如,这是在C/C++中:
PERSONCV p; // object/variable
int k = 0;
while ( k < N )
{
memcpy ( &p, &persons [ k ], sizeof ( PERSONCV ) ); // copies k'th elem
if ( p.age >= 18 )...
...
k++ ;
}
Run Code Online (Sandbox Code Playgroud)
Sim*_*ght 13
假设您使用的是GNAT,则有两种调查途径.
交换机-gnatG将重新生成类似Ada的表示,表示编译器的前端将传递到后端(在任何优化之前).在这种情况下,我明白了
function resander__jobcandidate return boolean is
iscandidate : boolean := false;
L_1 : label
begin
L_1 : for C8b in 1 .. 40000 loop
p : resander__personcv renames resander__persons (C8b);
if p.age >= 18 then
iscandidate := true;
exit;
end if;
end loop L_1;
return iscandidate;
end resander__jobcandidate;
Run Code Online (Sandbox Code Playgroud)
所以问题是,如何renames翻译?鉴于记录大小是2008字节,编译器生成副本的几率几乎为零.
第二种调查方法是保留编译器通常发送给汇编器的汇编代码,然后使用该开关删除-S.这证实生成的代码就像您的第一个C++版本(对于macOS).
作为一个有趣的侧面,Ada 2012允许替代实施jobcandidate:
function jobcandidate2 return Boolean is
(for some p of persons => p.age >= 18);
Run Code Online (Sandbox Code Playgroud)
它生成相同的代码.
我怀疑你读到的有关Ada的内容是错误的,而且可能更糟糕的是,鼓励你以错误的方式思考Ada.
Ada的目的是鼓励在问题领域进行思考,即指定应该发生什么,而不是在解决方案领域进行思考,即实现精确的细节.
所以这里的目的是遍历所有人,在第一次超过18时退出返回True,否则返回False.
就是这样.
一般来说,只要这些语义得到满足,Ada就不会详细说明它是如何完成的.
然后,意图是,你只希望编译器做正确的事情.
现在,单个编译器可以选择一个实现而不是另一个 - 或者可以根据优化启发式在实现之间切换,考虑它正在编译的CPU,以及对象的大小(它们是否适合寄存器?)等.
您可以想象一个具有许多寄存器的CPU,其中单个高速缓存行读取使得复制实现比在适当位置操作更快(特别是如果没有修改以回写到P的内容),或者反向为真的其他目标CPU.为什么要阻止编译器选择更好的实现?
这方面的一个很好的例子是艾达对参数传递到子程序的做法-名称,值或引用传递真的不适用-相反,您指定的参数传递模式- in,out或in out描述信息流(或)子程序.直观,提供可以更严格检查的语义,并使编译器可以自由选择正确遵循这些语义的最佳(最快,最小,取决于您的目标)实现.
现在,特定的Ada编译器可能会做出糟糕的选择,而30年前,当计算机根本不足以运行Ada编译器时,您可能会发现在编译器的早期版本中,为了简单起见,性能受到了损害.
但是我们现在有三十多年的编译器开发,在更强大的计算机上运行.所以,今天,我希望编译器能够正常地做出最佳选择.如果您发现某个特定编译器错过了性能优化,请提交增强请求.Ada编译器并不完美,就像任何其他编译器一样.
在这个具体的例子中,我通常希望P成为数组的游标,并且操作就地发生,即引用语义.或者可能是表单之间的混合,其中一个存储器提取到寄存器中用于多个操作,如部分形式的值语义.
如果您的兴趣是学术性的,您可以轻松查看您正在使用的任何编译器的汇编输出并找出答案.或者写上面的所有三个版本并对它们进