C/C++のconstキー

5852 ワード

今日1つの成り行きの笔记试験の问题をする时、やっと私にconstのキーワードをしっかりと総括する冲动があって、このキーワードの大小の多くの地方がすべて现れたことがあるため、现れる周波数はとても高くて、毎回ただ短い答えを见て、本当にその全体の使い方を理解していないで、すぐに仕事を探して、悲剧が再び発生することを避けるために、私の重視を引き起こさなければならなくて、これはやっとこの博文があります.
まずconstキーワードを見ると、私たちの最初の反応は定数を定義することです.確かに、これは間違いありません.constはconstantの略ですが、実際には彼の使い方はこれだけではありません.次に説明します.
Cプログラムでは、constの使い方には主に定数の定義、修飾関数パラメータ、修飾関数戻り値があります.C++プログラムでは、上記の機能に加えて、クラス内のメンバー関数が一定の関数であることを定義し、クラス内のデータメンバーを変更しないことを定義する関数の定義体を修飾することもできます.定数を定義する使い方については、ここではあまり説明しませんが、修飾関数パラメータ、修飾関数戻り値および修飾関数の定義体を重点的に見てみましょう.wbr>
1)修飾関数パラメータ
まず、このパラメータが出力に使用される場合、ポインタ伝達を採用しても参照伝達を採用してもconst修飾を加えることはできません.したがってconstは入力パラメータを修飾するためにのみ使用できます.ここでは、入力パラメータが値伝達を採用するか、ポインタ伝達を採用するか、参照伝達を採用するかの3つに分けられる.
(1)値伝達を採用する場合、関数によりこのパラメータをコピーするための一時変数が自動的に生成されるため、この入力パラメータは本来保護する必要がなく、だから修飾を加える必要はありません.span>
例えば、関数void Func 1(int x)についてvoid Func 1(const int x)と書くことは少しも意味がありません.同様に、void Func 2(A a)についてもvoid Func 2(const A a)と書く必要はなく、Aはユーザがカスタマイズしたオブジェクトタイプである.
(2)ポインタ伝達を用いる場合、constを加えることで、関数体内部のパラメータの変化を防止し、保護作用を果たすことができる.
例えば、StringCopy関数がvoid StringCopy(char*strDest,const char*strSrc)と定義されていると仮定すると、関数体がstrSrcの内容を変更しようとすると、コンパイラはエラーを報告する.
(3)参照伝達を用いる場合、
まず,なぜ参照伝達を導入するのかについて述べる.理由:非内部データ型のパラメータに対して、void Func(A a)のように宣言された関数は効率比が低いことに決まっている.関数内でタイプの一時オブジェクトを生成するため、パラメータタイプの一時オブジェクトをコピーするためにnormal;font-family:'Times new roman'」>a,一時オブジェクトの構造、複製、析出に時間がかかります.効率を上げるために関数宣言をvoid Func(A&a)に変更できます.これにより、参照伝達の定義に従って、パラメータの別名を借用しただけで、一時的なオブジェクトを生成する必要はありません.
しかし、これにより、関数体においてパラメータaの値が変化すると、対応する伝達元の値も相応に変化する.したがって、元のパラメータを変更したくない場合は、const修飾を前に付けるだけで、関数は最終的にvoid Func(const A&a)として定義されます.同様に、は、効率を向上させるためにvoid Func(int x)をvoid Func(const int&x)に書き換えるべきですか?内部データ型のパラメータには構造、解析のプロセスが存在しないため、レプリケーションも非常に速く、「値転送」と「参照転送」の効率はほぼ同等です.
関数入力パラメータとしてのconstの使い方をまとめます:
(1)非内部データ型の入力パラメータについては、「値伝達」の方式を「const参照伝達」に変更し、効率の向上を図る.例えばvoid Func(A a)をvoid Func(const A&a)に変更する.
(2)内部データ型の入力パラメータについて、「値伝達」の方式を「const参照伝達」に変更しないでください.そうでなければ効率の向上の目的は達成されず,関数の理解性も低下する.例えばvoid Func(int x)はvoid Func(const int&x)に変更すべきではない.
2)修飾関数の戻り値
上記の考え方によれば、ここでも値伝達、ポインタ伝達、参照伝達の3つのケースに分けられる.
(1)関数の戻り値が「値伝達」方式を採用すると、関数は戻り値を外部の一時的な記憶ユニットにコピーするため、const修飾を加えても何の価値もありません.
例えば、関数int GetInt(void)をconst int GetInt(void)と書かないでください.同様に、関数A GetA(void)をconst A GetA(void)と書かないでください.ここで、Aはユーザーがカスタマイズしたデータ型です.
(2)関数戻り値が「ポインタ伝達」方式である場合、関数戻り値(すなわちポインタ)の内容は変更できず、const修飾を加えた同型ポインタにのみ付与される.
たとえば、関数をconst char*GetString(void)と定義すると、char*str=GetString()にコンパイルエラーが発生します.const char*str=GetString()と書くべきです.
(3)関数の戻り値が「参照伝達」方式を採用している場合、その意味は、フィールドマージを使用することは多くないが、効率を提供できることである.このとき、は、関数がオブジェクトの「コピー」を返すか、「別名」だけを返すかを明らかにしなければなりません.そうしないと、プログラムがエラーになります.
例えば、クラスのリロード付与関数A&operate=(const A&other)についてcons修飾を加えない場合、A a,b,cを定義する.(a=b)=cで、プログラムは合法ですが、const修飾、すなわちconstA&operate=(const A&other)を加えると、プログラムはエラーを報告します.
3)関数の定義体を修飾する.
const関数を定義し、constキーワードを関数宣言の末尾に置くだけです.wbr>クラスを変更しないデータメンバーの関数はconstタイプとして宣言する必要があります.constメンバー関数を作成するときに、データ・メンバーを不注意で変更したり、他の非constメンバー関数を呼び出したりすると、コンパイラがエラーを報告し、プログラムの堅牢性が向上するに違いありません.
例えば、以下のプログラムでは、クラスstackのメンバー関数GetCountはカウントにのみ使用され、論理的にはGetCountはconst関数であるべきである.コンパイラはGetCount関数のエラーを示します.
class Stack
{
public:
  void Push(int elem);
  int Pop(void);
  int GetCount(void) const; // const     
private:
  int m_num;
  int m_data[100];
};
int Stack::GetCount(void) const
{
  ++ m_num; //     ,        m_num
  Pop(); //     ,     const   
  return m_num;
}
ここまででconstキーワードの説明は終わります.以下にconstを使用するいくつかのルールを示します.
1)constオブジェクトはconstメンバー関数にのみアクセスでき、constオブジェクトではなく任意のメンバー関数にアクセスできます.constメンバー関数を含む.
2)constオブジェクトのメンバーは変更できませんが、constオブジェクトがポインタで維持されているオブジェクトは変更できます.
3)constメンバー関数は、オブジェクトがconst特性を有するかどうかにかかわらず、オブジェクトのデータを変更することはできない.コンパイル時に、メンバーデータを変更するかどうかに基づいてチェックされます.
4)ただしmutable修飾子を加えたデータメンバーは、任意の場合に任意の手段で変更可能であり、この場合のconstメンバー関数は自然に変更可能である.