6

与其他语言不同,Chapel 中似乎没有用于在堆上分配数组allocatenew语法,而是使用通常的类似“声明”的语法。例如,在下面的代码中,我“声明”了两个数组AB一个基于形式(虚拟)参数的函数:

proc test( n, D )
{
    var A: [1..n] real;  // local array
    var B: [D] real;     // local array

    writeln( "A.domain = ", A.domain );
    writeln( "B.domain = ", B.domain );
}

test( 3, {2..5} );               // request small arrays
test( 10**7, {-10**7..10**7} );  // request large arrays

这给出了以下结果:

A.domain = {1..3}
B.domain = {2..5}
A.domain = {1..10000000}
B.domain = {-10000000..10000000}

因为没有发生堆栈溢出(尽管 的大小很大B),所以可以假设上述语法总是在堆上分配AB而不管它们的大小是多少?

此外,域变量的分配(或重新分配)似乎扮演着数组分配(或重新分配)的角色。例如,以下代码按预期工作。在这种情况下,分配是否总是发生在堆上(再次)?

var domC: domain(1);
var C: [domC] real;
writeln( "C = ", C );

domC = { 1..3 };       // assign a domain
C = 7.0;               // assign some value to the array
writeln( "C = ", C );

domC = { -1..5 };      // re-assign a domain
writeln( "C = ", C );

结果:

C = 
C = 7.0 7.0 7.0
C = 0.0 0.0 7.0 7.0 7.0 0.0 0.0

最后,用户是否不需要手动deallocatedelete这些数组,而是系统根据需要自动释放它们?

4

1 回答 1

4

是否可以假设上述语法总是在堆上分配 A 和 B 而不管它们的大小?

在 Chapel 1.15.0 中,Chapel 数组元素始终分配在堆上。我们已经讨论了添加机制(例如,自定义域映射)或可能用于在适当时将数组元素存储在堆栈上的优化,但还没有追求这些功能。请注意,虽然数组的元素是在堆上分配的,但数组也是使用“就地”分配的运行时描述符实现的(例如,在您的示例中的堆栈上)---此描述符指的是堆分配的元素.

此外,域变量的分配(或重新分配)似乎扮演着数组分配(或重新分配)的角色。

这是正确的,值得强调的是,这是一个逻辑上而不是面向物理的重新分配概念。具体来说,当重新分配数组的域时,如果在旧域的索引集中和新域的索引集中,A[i]将继续存储相同的值。i这就是为什么当您在上面的代码中domC{1..3}更改为时,它被保留了,因为它代表了两个集合的交集。{-1..5}A[1..3]

分配是否总是发生在堆上(再次)?

是的,与初始数组分配一样。

用户是否不需要手动释放或删除这些数组,而是系统根据需要自动释放它们?

没错,数组内存管理通常由实现来处理。手动管理数组内存的一种方法是使用带有数组字段的类变量(因为类是手动管理内存的)。

于 2017-06-06T04:45:22.247 回答