2011-12-15 14 views
16

私はconst refinの違いを理解するために、特にパフォーマンスに関しては理解しています。'const ref'と 'in'の違いは?

  1. 私はinconst scopeと同等であることを知っているが、the scope stor­age class means that ref­er­ences in the pa­ra­me­ter can­not be es­caped (e.g. as­signed to a global vari­able).は何を意味するのでしょうか?サンプルコードは大歓迎です。

  2. 機能を実装するときにconst refinをどのようにして決定しますか?私はrefと知っています。オブジェクトは参照であるためコピーされませんが、inでは同じですか?

答えて

10

1)scopeパラメータ格納クラスは、パラメータへの参照をエスケープできないことを意味します。例:

Object glob; 

struct S 
{ 
    Object o; 
    void foo(scope Object o) 
    { 
     this.o = o; // Not allowed! 'o' must not be escaped 
     glob = o; // ditto 
    } 
} 

DMDはこれを検出するのにあまりよくないことに注意してください。上記の例は現在コンパイルされていますが、許可されていません。

scopeは、デリゲートのパラメータのために最も有用である:上記の例で

void foo(scope void delegate() dg) 
{ 
    /* use dg */ 
} 

void main() 
{ 
    int i; 
    foo({ ++i; }); 
} 

ことがある(foo「保証」するので、何の閉鎖は、それが上位値を持っているにもかかわらず、匿名関数のために割り当てる必要がありませんコンパイラの仕事...)は、デリゲートがエスケープされていないことを示します。 DMDは現在、この最適化を実装しています。

2)考えているのは、constscopeの両方を使用すると、理論的にコンパイラがリファレンスまたは値を渡すことができるということです。そのため、inショートカットが便利です。 DMDはこれを今は利用していませんが、それにもかかわらず便利なショートカットです。

簡潔に言えば、inは、現在、代理人で使用されていない限り、パフォーマンスを得ることはできません。 refは、大きな構造体または静的配列でパフォーマンスを向上させます。パフォーマンス上の理由からrefを使用すると、constは、refではなく、が元の値を更新するために使用されていることを文書化(および実施)することがよくあります。

+0

1.私は効果を再現できなかった理由を説明します。 2.関数のパラメータが 'in'ストレージクラスを持っていれば、それはコピーされると言っていますか? 'const ref'を使うべきですか? – Arlen

+0

現在のコンパイラ選択では、すべてDMDに基づいてコピーされます。しかし、それについての素敵なことは、ユーザーが違いを知ることができないため、技術的に定義された実装であるということです。 DMDが最適化のためにこれを利用するには、まず 'scope'を完全に実装する必要があります。コピーをボトルネックとして特定し、最適化したい場合は、 'const ref'を使うのは良い考えです。 –

+0

DMDについてどう知っていますか?あなたはコア開発者の一人ですか? – Arlen

10
  1. scopeパラメータが機能をエスケープすることは正しくありません。コンパイラは、そのデータへの参照が関数をエスケープしないことを保証することになっています。主にデリゲートで使用されます。デリゲートがエスケープしないことを知っているので、コンパイラーはクロージャーの割り当てを避けることができるためです。

  2. const refはと同じですが、変数はコピーされる代わりに参照によって渡されるため、コピーを避けることができます。しかし、はC++と異なりconst refです。ではありません。はrvaluesで動作します。 に左辺値を指定する必要があります。したがって、パラメータをconst refと宣言すると、それに渡すことができるものが制限されます。 inは一時的に受け入れるのに対し、一般に変数を宣言して渡す必要があります。

    void func(const ref int var) {} 
    int a; 
    func(a); //legal 
    func(7); //illegal 
    

funcconstまたはinを取った場合、それらの呼び出しの両方が法的になります。したがって、一般的には、const refまたはinを使用するかどうかは問題ではありません。問題はconstinのどちらを使うべきかです。その場合は、scopeを使用するかどうかは、両方ともconstであるため、問題になります。渡す変数への参照がその関数をエスケープしないようにするには、scopeを使用します。したがって、一般に代理人でのみ使用されますが、クラスや配列では便利です。

ただし、機能上のpureは、その引数のいずれかへの参照がそう、戻り値(彼らは不変だか、ある値の型をし、constのであればpure関数は、グローバル変数のみを使用することができますので)経由以外から逃れることはできないことを保証しますpureは、一般に、クラスと配列であるパラメータに必要なものすべてを提供します。さらに、戻り値の型がクラスまたは配列の場合、引数をエスケープできないようにする必要はありません。戻り値の引数から何かを再利用できるのではなく、コピーを作成することが強制されますが、これは一般に効率が悪いものです。

したがって、scopeは、一般的には代理人だけが使用しますが、クラスや配列では便利です。とにかく関数はpureであることが既に一般的には好ましいので、この問題の大半は処理されます。したがって、inを使用しても傷つきませんが、constの代わりにinを使用してもほとんど意味がありません。渡される変数を実際にコピーしたくない場合は、通常はconst refしか使用しません。それ以外の場合は、その関数にlvaluesを渡すことしかできないためです。 は、バージョンがconst、それにはconst refが含まれていますが、明らかにコードの重複が発生するような機能をオーバーロードします。実際にconst refが必要な場合を除き、constを使用することをお勧めします。

EDIT:

scopeまだ(2013年6月18日のような)委任以外のために実施されなければならないので、委任以外でscope又はinのいずれかを使用して無分別です。現時点では、彼らは誤解を招く恐れがあります。scopeが代理人以外に実装されている場合、scopeまたはinがエスケープされている変数への参照によってコードが壊れる可能性が高くなります。

+0

'スコープ'がDMDに完全には実装されていないため、 'in'はそれほどうまくいきません。 'in 'を間違って使用した人のために' scope'が完全に実装されると、それは急激な変化ではないでしょうか? – Arlen

+0

'scope'がバグだとすると(これは非常にうまくいくかもしれませんが、私はそれをあまり使わないので、現在の状態は正確にはわかりません)、そうです。 'scope'や' in'を間違って使用しましたが、これはコンパイラのバグとほぼ同じです。幸いにも、dmdのこのような問題の数はgithubに移行して以来、急速に発展しているため大幅に減少していますが、機能が正しく実装されていない問題に対処することは可能です。 –

+0

'scope'は実際にはバグではなく、最適化を除いてはまったく実装されていません。 'pure'メンバ関数を使うと、それをメンバフィールドに代入してエスケープすることができ、' pure'は他の無関係な制限を持つので、 'pure'は' scope'の良い代替手段になることはめったにありません。 'scope'が完全に実装されていれば、' scope'で受け取った関数にスタックを安全に渡すことができるなど、非常に多くの場合に便利です。 –

関連する問題