人を愛し憎むconst

4400 ワード

constといえばよく知っているかもしれませんが、ぼんやりしているかもしれません.あなたの認識は間違いないかもしれませんが、一面的すぎるかもしれません.簡単なconstを使うと、あなたはすべてできますが、複雑なconstを使うと、あなたは瞬間的に愚かになります.では、constがいったい何ができるかをよく見るべきです.まずCとC++でのconstの使い方の違いを紹介し、C++のconstの最適化や、C++でのconstや引用については、多くのことを話します.1.まずC言語とC++におけるconstの違い(1)まず,C言語におけるconstが定数である.コンパイラはこの量を保存するためにメモリ領域を直接開きますが、他には最適化されていません.しかし、C++ではconstant foldingというメカニズムが使用されており、定数の値をメモリとは関係なく、その定数値を保護しています.(2)c言語でconstはデフォルトの外部接続を使用する.C++では内部接続、c++ではconstはlocalファイルであり、本ファイルのみが表示されます.他のファイルも表示されるようにするには、その前にexternキーを付けます.C言語ではconstの役割ドメインはグローバルです.
2.違いを言い終わったらconstの使い方を話しましょう(1)C++でconst int a=10;aを使う価値がある場合、コンパイラは直接置換最適化を行い、直接aを10に置換します.aを使用すると、コンパイラはメモリ領域の読み取りを行わないため、前述した定数折り畳みメカニズムです.すなわち、定数をシンボルテーブルに配置してメモリを割り当てることはありません.aのメモリ領域を使用する場合を除き、コンパイラはメモリを割り当てることができませんが、その後の操作ではシンボルテーブルから読み取ります.aの記憶空間がどのように変化しても、定数aに影響を及ぼすことはない(2)constを加えたものは一定の定数ではなく、constの右側にポインタが存在する場合にのみconstが影響を与え、constは常にそれに最も近い識別子と結合する(例えば、const char*、constはcharと結合するだけで、char*と結合するわけではないので、これも私たちが今後犯す可能性のある間違いです);(3)C++では、メンバーメソッドはconst修飾であってもよいが、一定のルールを守らなければならないのは、通常のメソッドではなく、通常のメソッドでは通常のメソッドを呼び出すことができることである.(4)constがリファレンスと一緒に使用するのは、リファレンスの後のパラメータが定数であり、定数はアドレスを取得できないため、リファレンスが通常リファレンスになって使用できます.
次に、犯しやすい間違いについていくつか説明します.
class Test
{
public:
    Test(int data=10):_ptr(new int(data)){}
    ~Test(){delete _ptr;}
    int* GetIntPtr(){return _ptr;}
    int* GetIntPtr()const{return _ptr;}
    int*& GetIntPtrRef(){return _ptr;}
    int*const& GetIntPtrRef()const{return _ptr;}// int *const 
private:
    int *_ptr;
};

int main()
{
    Test t1;
    const Test t2;
    int *&b1 = t1.GetIntPtr();
    const int *&c1 = t1.GetIntPtr(); 
    int *&b2 = t2.GetIntPtr();
    const int *&c2 = t2.GetIntPtr();
    return 0;
}//              ,           

まずやってみてください.これらの問題は簡単ですが、等号の左右のそれぞれのタイプをはっきり区別すれば、問題ありません.私がここで挙げたこれらの方法の呼び出しにはすべて間違いがあります.一つ一つ見てみましょう.
このような問題には、戻り値が値であること、ポインタであること、参照であることが含まれています.肝心なのは、これらの点です.1.戻り値の場合、等号の左右のタイプが等しいかどうかを判断するだけです.2.戻り値がポインタの場合、タイプは等しいか、戻り値がアドレスを消すことができるかを要求します.つまり、参照を解く*3.参照を返すとき、受信を見てみましょう.定数は常引用で、肝心なのは右を引用して住所を取ることができるかどうかです
理解してみてはいかがでしょうか.
int main()
{
    Test t1;
    const Test t2;
    int *a1 = t1.GetIntPtrRef();
    int *&b1 = t1.GetIntPtrRef();  
    const int* &c1 = t1.GetIntPtrRef();  
    int *a2 = t2.GetIntPtrRef();    
    int *&b2 = t2.GetIntPtrRef();
    const int *&c2 = t2.GetIntPtrRef();
    return 0;
}

//ここには間違いがある
ここでは、1.最初の2つは間違っていません.引用を返すと自動的に引用が解けます.2.しかし、3つ目から問題が来ました.これは発見しにくい間違いです.ここでは、私たちが戻ったときにint*を返しました.(引用は参加しませんタイプ)ああ、でも左側はconst int*&、よく理解しなければconst int*c 1=&t 1.GetIntPtrRef();ある意味、(元のコードで)左のconstは*c 1を修飾して、それはc 1が修正されないことを保証して、あなたの原式はintを書いて、保護されていないので、両側を同じにして、const int*const&c 1=t 1.GetIntPtrRef()に変えます;3.残りは簡単で、最も簡単にタイプを見て判断することができて、最後の2つはすべてint*の後ろでconstが欠けています.
私は文章の中に間違いや抜け穴があるに違いないと思っています.編集能力が限られているかもしれません.読者の皆さんが早く間違いを指摘して、一緒に勉強して進歩してほしいと思っています.