教堂什么时候通过引用,什么时候通过常量?



我正在寻找教堂通过引用的例子。 这个例子有效,但它似乎是糟糕的形式,因为我正在"返回"输入。 这会浪费内存吗? 有没有对类进行操作的显式方法?

class PowerPuffGirl {
var secretIngredients: [1..0] string;
}
var bubbles = new PowerPuffGirl();
bubbles.secretIngredients.push_back("sugar");
bubbles.secretIngredients.push_back("spice");
bubbles.secretIngredients.push_back("everything nice");
writeln(bubbles.secretIngredients);
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
bubbles = kickAss(bubbles);
writeln(bubbles.secretIngredients);

它产生输出

sugar spice everything nice
sugar spice everything nice Chemical X

使用函数修改气泡的最有效方法是什么?

Chapel 是否通过引用传递参数可以通过参数意图来控制。例如,整数通常按值传递,但我们可以通过引用传递一个:

proc increment(ref x:int) { // 'ref' here is an argument intent
x += 1;
}
var x:int = 5;
increment(x);
writeln(x);                 // outputs 6

类型在未指定参数时传递的方式称为默认意向。默认情况下,Chapel 通过引用传递记录、域和数组;但是在这些数组中,只有数组可以在函数内部修改。(记录和域通过const ref传递 - 这意味着它们是通过引用传递的,但它们传递给的函数无法修改它们。数组传递refconst ref取决于函数对它们的处理 - 请参阅数组默认意图)。

现在,具体到您的问题,类实例默认按"值"传递,但 Chapel 认为类实例的"值"是一个指针。这意味着,与其允许字段(比如)被改变,不如通过ref传递类实例,只是意味着它可以被不同的类实例替换。目前没有办法说类实例的字段不应该在函数中修改(除了使它们成为显式不可变的数据类型)。

鉴于所有这些,我认为您在问题中提供的代码示例没有任何效率低下的地方。特别是在这里:

proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}

接受b的参数将接收指向实例的指针的副本,return b将返回该指针的副本。实例的内容(特别是secretIngredients数组)将保留在原来的位置,并且不会在此过程中复制。

还有一件事:

这个例子有效,但它似乎是糟糕的形式,因为我正在"返回"输入。

正如我所说,这对于类实例或整数来说并不是真正的问题。数组呢?

proc identity(A) {
return A;
} 
var A:[1..100] int;
writeln(identity(A));

在此示例中,identity()中的return A实际上会导致创建数组的副本。当数组传入identity()时,该副本不是创建的,因为数组是带着const ref意图传递的。但是,由于该函数返回作为引用的"按值"返回的内容,因此有必要将其作为返回的一部分进行复制。另请参阅语言演进文档中默认按值返回的数组

在任何情况下,如果想要通过引用返回数组,可以使用refconst ref返回意图来实现,例如:

proc refIdentity(ref arg) ref {
return arg;
}
var B:[1..10] int;
writeln(refIdentity(B));

现在没有数组的副本,一切都只是引用相同的B.

请注意,目前可以编写程序来返回对不再存在的变量的引用。编译器在该区域包含一些检查,但它并不完整。希望该领域的改善很快到来。

相关内容

  • 没有找到相关文章

最新更新