2011-12-30 10 views
0

何が起こっているのか分かりません。私はC++を学んでいると私はこのロットのようなものを参照してください。私たちは参照渡しされている場合const&doは何ですか?

double some_function(const Struct_Name& s) { 
    ... 
} 

なぜconstを?

+2

何本ものは徹底的にカバーしていないから、あなたがC++を学んでいる[constの-正し](http://en.wikipedia.org:これは通常は一時的にはそのような状況で使用すべきではないことを示すものです/ wiki/Const-correctness)? – ildjarn

+1

const-correctness _is_重く、C++で混乱しますが、実際にこのことを学び理解する必要があります。間違っていると、コードがコンパイルされず、理由を理解できなくなります。 – cha0site

答えて

4

const参照は、constのようにオブジェクトが変更されるのを防ぎますが、コピーする可能性もありません。

+0

参照は変更不可能ですが、これは単なるアドレスです。あなたが言っているのは、この特定のビットのメモリがアクセスされ、この関数の範囲内でメモリのこの特定のセクションに書き込みが許可されていないと読んだときです。 – lollercoaster

+0

これらの行に何かがあります。参照渡しは、ポインタを渡すのと似ていますが、const参照渡しの構文は他の引数と同じです。書く限り、コピーされたconstオブジェクトと同じ強制を適用できますが、システムを破壊することなく、constメソッドだけが呼び出され、オブジェクトに書き込むことはできません。目的は、コピーを実行せずに大きなオブジェクトを渡すことです(コレクションの場合は深いコピーになる可能性があります)が、通常の構文を使用して標準の定数を適用します。 – ssube

+1

@lollercoaster:constが適用されている参照ではなく、それが指示対象です。とにかく参照を再割り当てすることはできないので、参照をconstにする意味がありません。 '(Struct_Name&const s)'のようなものではありません: '(const Struct_Name&s)' –

2

Struct_Nameのコピーは、const-referenceによって呼び出されることはありませんが、変更しないことを約束します。

パフォーマンスの理由と意味論の理由の両方があります。

Struct_Nameが大きい場合、コピーは時間とメモリの両方で高価です。

Struct_Nameがコピー不可の場合(またはコピー時に無効になる場合)、値での呼び出しは不可能であり、望ましくない複雑さを招きます。たとえば、std::unique_ptrおよびstd::auto_ptrです。

4

渡された引数を変更したくない(または変更できない)ときにconst参照を渡し、オブジェクトのコピーによって得られるパフォーマンスが低下しないようにしたい場合。

+0

@ildjarn:あなたのケースでは、コピーで引数を渡します。 –

+0

@eharvest:私の主張は、非const参照を取ることは、const参照を取る間に一時的に渡すことができないということでした。 (すべての後、OPは特に、参照によって渡されたときに 'const'が提供するメリットを疑問視しています。一時的なものがそのメリットの1つです) – ildjarn

2

コンパイラにあなたは今まで変更しないことを伝えています。

これにより、それ以外の方法ではできなかった最適化が可能になります。基本的には、値渡しと同じセマンティクスを提供しますが、コピーコンストラクターを呼び出す際のパフォーマンス上のペナルティは発生しません。

+1

値渡しとconst参照渡しのセマンティクスは同じではありません。マルチスレッド環境では、前者の場合とは異なり、オブジェクトの存続期間に関する保証はありません。 – ildjarn

2

constを使用することにより、関数のユーザと、引数sとして渡されたオブジェクトが関数内で変更されないことをコンパイラの両方に通知できます(実際には可能です)。事故によってオブジェクトを修正すると、コンパイラはエラーを返すことがあります。それ以外の場合はできない最適化を行うことができます。

さらに、オブジェクトのポインタがconstのポインタを所有している場合でも、そのオブジェクトをキャストせずに引数として渡すことができるという利点があります。ここ

1

constが、あなたがそれを修正しようとすることができますが、コンパイラはエラーを返します

double some_function(const Struct_Name& s) { 
    ... 
} 

、some_functionは、Sパラメータを変更しないことpromisses。実際にはconstは、Struct_Nameの内部メソッドを慎重に記述する必要があります。 some_functionの非const関数をsオブジェクト上で呼び出すことはできません。試すことはできますが、エラーが発生します。すなわち:あなたには、いくつかの機能は、あなたがconstのを追加するには、オブジェクトを変更することが想定されていないわかっている場合のconstパラメータを使用して

struct Struct_Name { 
    void myfun() const { } // can be called from some_function 
    void myfun2() { } // will show error if called from some_function 
}; 

は、設計の観点から良いです。これは、深く隠されたクラス階層コードの変更を他のプログラマが行うことができないことを意味します。これは本当にデバッグを容易にします。

1

まだ誰も言及していないもう一つの理由 - const参照を渡すことで、コンパイラは、入力値がパラメータで宣言された正確な型ではなく型を宣言することなく、渡されるタイプをサポートしてコンストラクタを持っている

たとえば:。

void foo(const std::string &s) 
{ 
    ... 
} 

foo("hello"); // OK 

foo()std::stringを期待してではなくconst char*を受けています。 std::stringconst char*を受け入れるコンストラクタを持ち、コンパイラはこれを効果的にやっているコードを生成するので:

std::string temp("hello"); 
foo(temp); 

コンパイラはパラメータがconstであることを知っている、一時的にはfoo()によって変更されず、一時的に破棄されますfoo()が終了した後、一時的なものを作成しなければならないと不平を言うことはありません。

パラメータは値渡し(constまたは非const、それは問題ではない)の代わりに、参照することによりされている場合、同じことが起こる:

void foo(const std::string s) 
{ 
    ... 
} 

void bar(std::string s) 
{ 
    ... 
} 

foo("hello"); // OK 
bar("world"); // OK 

これが効果的にこれと同じです

{ 
std::string temp1("hello"); 
foo(temp1); 
} 

{ 
std::string temp2("world"); 
bar(temp2); 
} 

また、コンパイラは、一時コードが呼び出しコードに影響を及ぼさないことを知っていて、bar()の一時的な変更は安全に破棄されます。

パラメータがconstの参照ではなく、const char*を渡すと、参照バインディングを満たすために作成する必要がある一時的な警告が生成されます。この警告は、関数が終了したときに関数が一時的に行った変更(constではないため)が失われることを通知するものです。これは呼び出し元コードに影響する場合としない場合があります。

void foo(std::string &s) 
{ 
    ... 
} 

foo("hello"); // warning! 
関連する問題