2017-11-29 4 views
3

私は参考資料として渡されたチャペルの例を探しています。この例では動作しますが、入力を「返す」ので、悪いフォームのように見えます。これは記憶を浪費するか?クラスを操作する明確な方法はありますか?チャペルはいつ参照で渡されますか?

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 

を生成?

答えて

5

チャペルが参照によって引数を渡すかどうかは、引数intentによって制御できます。例えば、整数は通常、値渡しが、我々は、参照することによって1を渡すことができます:

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

方法をあなたは引数がデフォルトの意思として知られている指定されていない時に型が渡されます。チャペルは、デフォルトでレコード、ドメイン、および配列を参照渡しします。これらの配列の中でのみ、関数内で変更可能です。 (レコードとドメインがconst refを通過 - 彼らは参照によって渡されますが、それらはに渡される関数は、それらを変更することができないことを意味配列は、機能は彼らと何をするかに応じて、refまたはconst refを通過 - 。array default intentを参照してください) 。

あなたの質問には、クラスインスタンスはデフォルトで "値"で渡されますが、チャペルはクラスインスタンスの "値"をポインタと見なします。つまり、フィールドを変更する代わりに、クラスインスタンスを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は、実際には配列のコピーがなされるべき 原因を行います。アレイがconst refインテントで渡されたため、アレイをidentity()に渡すときにそのコピーが作成されませんでした。しかし、この関数は参照である "値で"何かを返すので、返り値の一部としてそれをコピーする必要があります。言語進化文書のarrays return by value by defaultも参照してください。いずれの場合においても

、1は参照によって配列を返すしたい場合、それはrefまたはconst refリターンの意図、例えばでそうすることが可能です:

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

今の何のコピーはありません配列などはすべて同じものを指していますB

現在、もはや存在しない変数への参照を返すプログラムを書くことは可能ですが、コンパイラにはその領域のチェックが含まれていますが、完全ではありません。その地域での改善が間もなくできることを願っています。

関連する問題