2012-06-12 13 views
15

プロシージャ内でconstパラメータを使用すると、どのような違いがありますか?プロシージャのパラメータに "const"を使用すると、どのような違いがありますか?

例えば、以下の手順を取る:

procedure DoSomething(Sender: TObject; const Text: String; var Reply: String); 
begin 
    //Text is read-only and Reply will be passed back wherever DoSomething() was called 
    Reply:= Text; 
end; 

(私の知る限り)、値のコピーが作られ、使用されているように、パラメータText: Stringconstが付いている - と読み取り専用であります。私が疑問に思っていたことは、アプリケーションに何か違う影響を与えるのは、constを入れなかった場合とはどういうことでしょうか?おそらくパフォーマンスのトリックですか?

+1

ここで答えますか? http://stackoverflow.com/a/1601124/496736 –

+2

ほとんどの場合、すべての入力専用パラメータを「const」として注意深くマーキングすることの大きな利点は、プログラマが、あなたが愚かなことを避けるために追加の助けを得ることですバグ。 –

+1

@Andreas何が嫌なのは、インターフェイスと実装の両方に 'const'を含める必要があることです。これは、C++がDelphiに勝つ1つの領域です。 –

答えて

22

「のconstを使うには、コンパイラが構造化のためのコードを最適化することができます - と、文字列型のパラメータをまた、意図せずに別のルーチンを参照することによってパラメータを渡すに対する保護を提供します。」

たとえば、文字列の場合、最適化は、constとして渡すときに追加の参照カウントがないことを意味します。 constとして渡すこともではなく、というのはそれがコピーであることを意味します。コンパイラは書き込みアクセスを保証しないため、内部的に参照として渡すことがよくあります。

は、いくつかの非常に興味深い記事completlyフードの下で何が起こっているかを理解する:

http://delphitools.info/2010/07/28/all-hail-the-const-parameters

http://vcldeveloper.com/articles/different-function-parameter-modifiers-in-delphi

編集:

でパスをもたらすことができるというのconstを表示するための簡単な例内部参照:

program Project1; 

{$APPTYPE CONSOLE} 

type 
    PMyRecord = ^TMyRecord; 
    TMyRecord = record 
    Value1: Cardinal; 
    Value2: Cardinal; 
    end; 

procedure PassAsConst(const r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

procedure PassByVal(r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

var 
    r: TMyRecord; 
begin 
    r.Value1 := 1111; 
    r.Value2 := 2222; 
    PassByVal(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    PassAsConst(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    Readln; 
end. 
+3

FWIW:**渡された**については、パラメータがconstかどうかは関係ありません。明示的に 'var'または' out'と宣言されていなければ、constまたはnon-constに対して**渡されます**。一般に、レジスタサイズ(例えば32ビット)より大きなアイテムは、constであるかどうかにかかわらず、参照によって**渡されます。 constとnon-constの唯一の違いは、非constの場合、項目をローカルストレージにコピーする最初に隠れたコードが挿入されることです。 constの場合は、参照の参照のみが許可されているので、このコピーコードはなく、渡された参照は直接使用されます。 –

6

const接頭辞がない場合、コンパイラはパラメータを変更すると想定する必要があります。これは、それをコピーし、隠されたtry ...最終的にローカル文字列変数を処分するように設定することを意味します。したがって、時にはconstが大幅にパフォーマンスを向上させることがあります。また、生成されたコードを小さくします。 documentationの状態を見てみると

+0

これは、私がインストールした最新のDelphi 2007の時点で当てはまると付け加えておきます。より高度なコンパイラでは、パラメータが実際にconstプレフィックスなしで変数として使用されていてコピーされていないことを潜在的に検出する可能性がありますが、これらのタイプの最適化は歴史的にDelphi R&Dチームの焦点では​​ありませんでした。 –

+0

constパラメータを知っているすべてのバージョンのDelphiでは、D2007の前に構造体をコピーする必要はありません。構造体が参照によって渡された場合(サイズに依存します)、ローカルストレージに参照カウントを行う必要はありません。 –

1

constを使用した場合の効率の以前の回答(つまり、コンパイラーは変数をコピーする必要はありません).Interfaceパラメーターでconstを使用すると、参照カウントのトリガーを防ぐことができます。

+0

この動作の理由は次のとおりです。http://qc.embarcadero.com/wc/qcmain.aspx?d=75036 –

+3

参照カウントの欠如は、インターフェイスと文字列では同じです。あなたがインターフェースについて語ったことは、文字列に関するものに "加えて"ありません。 *変数*は常にコピーされますが、ポインタの値をコピーするだけなので、コピーするのが安いです。値をあるレジスタから別のレジスタにコピーするだけではありません。 –

関連する問題