ここの初心者、私はいくつかのコードを読んでいます、そして私は時々作者が関数で参照を次のように使用したのを見ます
funca (scalar& a)
// Etc
時々彼はただ使う
funcb (scalar a)
// Etc
違いは何ですか?参照を使用することは私が持つべき良い習慣ですか?
ありがとうございました!
ここの初心者、私はいくつかのコードを読んでいます、そして私は時々作者が関数で参照を次のように使用したのを見ます
funca (scalar& a)
// Etc
時々彼はただ使う
funcb (scalar a)
// Etc
違いは何ですか?参照を使用することは私が持つべき良い習慣ですか?
ありがとうございました!
を呼び出すと、 typefoo(scalar a)
の引数は呼び出し元からコピーされ、fooは元のオブジェクトの独自のCOPYを持ちます。a
scalar
を呼び出すfoo(scalar &b)
と、引数b
は元のオブジェクトへの単なる参照になるため、変更することができます。
指定されたオブジェクトのコピーの作成を回避するため、&name構文を使用して参照によってオブジェクトを渡す方が高速ですが、実際のコピーが必要なため、潜在的に危険であり、動作が望ましくない場合があります。
そうは言っても、実際には、呼び出された関数の元のオブジェクトを変更する機能を許可しないが、コピーの作成を回避するオプションがあります。これは、呼び出し元が引数として渡されたオブジェクトをfoo(const scalar &x)
関数が変更することを望まないことを明示的に示しています。foo
オプションの読み方、注意深く:
引数を生のポインタとして渡す方法もありますが、これは最近のC++では非常にまれです。注意して使用してください:foo(scalar *a)
。このシナリオでは、呼び出し元はオブジェクト自体ではなくオブジェクトのアドレスを提供する必要があるため、呼び出し元はを呼び出しますfoo(&a)
。この場合、呼び出された関数foo
がオブジェクト自体を変更できるようにするには、次のようにポインターを逆参照する必要があります。この場合の変数名の前の星印は、受け取ったアドレスを変更したくないことを示しています(呼び出し元の関数が提供する直接の結果、つまりオブジェクトaのアドレスとして)。a
foo
*a =
&a
参照によってパラメーターを渡すと、呼び出された関数は、関数が戻った後に呼び出し元に表示されるように引数を変更できます。一方、値を渡すと、変更の範囲が呼び出された関数に限定されます。したがって、(非const)参照を渡すことは、通常、呼び出し先が引数を変更するか、まれに追加の「戻り値」として使用することを意味します。
さらに、参照渡しは、パラメーターのコピーを作成する必要がないことを意味します。値を渡すには、そのようなコピーが必要です(これは、アプリケーションのメモリフットプリントまたは実行時のパフォーマンスに悪影響を与える可能性があります)。このため、クラスタイプの引数が参照として渡されることがよくありますconst
。呼び出し先は引数を変更するつもりはありませんが、コピーが作成されるのを避けたいとも考えています。スカラー引数のサイズは非常に小さいため、このアプローチのメリットはありません。
C++での参照渡し/値も参照してください。
値(funcb (scalar a)
)で呼び出すと、関数に引数のコピーが提供されるため、引数に加えられた変更は呼び出し元には表示されません。
参照による呼び出し(funcb(scalar& b)
)は、関数が引数を直接操作することを意味するため、加えられた変更は呼び出し元に直接表示されます。
参照による呼び出しが良い習慣であるかどうかは、状況によって異なります。引数を変更する関数(および呼び出し元に表示される変更)が必要な場合は、明らかに参照による呼び出しを使用する必要があります。非定数参照引数を使用して引数を変更したくない場合は誤解を招く可能性があるため(署名は引数が変更される可能性があることを示しているため)、ここでは値による呼び出しがより適切です。もちろん、より複雑なタイプの場合、値による呼び出しは重要なオーバーヘッドを持つ可能性があります。このような場合、const-referenceによる呼び出しが望ましいです(funcc(const scalar& c)
)