引用、ポインタ、const、パラメータ伝達の関係を理解する


引用、ポインタ、const、パラメータ伝達の関係を理解する
前言
「剣指offer」で質問を見た.書いた関数にポインタを入力する必要がある場合、面接官はそのポインタにconstを追加する必要があるかどうか、constをポインタの異なる位置に追加する必要があるかどうかを聞く可能性がある.書かれた関数が入力するパラメータが複雑なタイプのインスタンスである場合、面接官は、入力値パラメータと入力参照パラメータの違い、入力参照パラメータにconstを付ける必要があるタイミングを尋ねる可能性があります.鼻を触って、自分が愚かな顔をしていると自問して、答えられない.参照、ポインタ、const、パラメータ伝達に関する知識は混同されています!
一、const限定子
1、constオブジェクトが作成されると、その値は変更できません.constオブジェクトは初期化する必要があります.
2、オブジェクトのタイプはその上の操作を決定し、constタイプでない操作に比べてconstタイプのオブジェクトはその大部分を完成することができるが、すべての操作が適しているわけではない.主な制限はconstタイプのオブジェクトでのみコンテンツを変更しない操作を実行できます.
3、constオブジェクトを変更しない操作のもう1つは初期化であり、1つのオブジェクトを利用して別のオブジェクトを初期化し、それらがconstであるかどうかは重要ではない.
二、引用は何ですか.
1、参照は別名です.参照はオブジェクトではありません.逆に、既存のオブジェクトに付けられた別の名前にすぎません.
2、参照を定義するとき、プログラムは、初期値を参照にコピーするのではなく、参照とその初期値をバインドします.初期化が完了すると、参照は初期値オブジェクトと常にバインドされます.
3、リファレンスを別のオブジェクトに再バインドできないため、リファレンスを初期化する必要があります.
4、参照タイプは、バインドされたオブジェクトと厳密に一致します(2つの例外があります).参照はオブジェクトにのみバインドされ、フォント値や式の計算結果にバインドされません.
5、constの引用:
5.1、定数参照:「定数参照」は「constへの参照」の略称である.5.2.constオブジェクトに参照をバインドできます.通常の参照とは異なり、定数の参照はバインドを変更するオブジェクトとして使用できません.
    const int ci = 123;
	const int &r1 = ci;   //   :             
	r1 = 42;              //   :r1       
	int &r2 = ci;         //   :                  

5.3、第一の例外:定数参照を初期化する時、任意の式を初期値として使用することを許可する.この式の結果が参照のタイプに変換できる限り.特に、オブジェクト、フォント値、さらには一般的な式を定数参照にバインドできます.
	int i = 123;
	const int &r1 = i;       //    const int&       int   
	const int &r2 = 123;     //   :r1       
	const int &r3 = r1 * 2;  //   :r3       
	int &r4 = r1 * 2;        //   :r4           

理由:定数参照riが別のタイプのオブジェクトtiにバインドされると、コンパイラは一時量オブジェクトtempを生成します.この場合、riはこの一時量対像tempにバインドされ、この一時量オブジェクトtempのタイプはriタイプと一致します.すなわち、tiのタイプは参照のタイプに変換されます.riが定数でない場合、riに値を割り当てることが許可され、参照オブジェクトの値(本意)を変更することができますが、riバインドされたオブジェクトは実際には一時量オブジェクトtempであり、本意に反します.
5.4、constへの参照はconstでないオブジェクトを参照することができる.定数参照は、参照が関与する操作のみを限定し、参照されるオブジェクト自体が定数であるかどうかは限定されません.一般的には、オブジェクト自体は大名であり、定数参照は小名であり、小名ではオブジェクトの値を変更することはできませんが、大名はできます.
6、パラメータ伝達——引用伝達:
6.1.参照呼び出し:参照タイプである場合、対応する実パラメータと呼ばれる実パラメータが参照されて渡され、参照パラメータはそのバインドオブジェクト(対応する実パラメータ)の別名である.実パラメータの値がパラメータにコピーされると、パラメータ実パラメータは、伝達呼び出し、すなわち値伝達と呼ばれる2つの互いに独立したオブジェクトです.
6.2、伝達参照パラメータ:参照パラメータを使用することにより、関数が1つ以上の実パラメータの値を変更することができる.
//        int  ,          0
void reset(int &i)        
{
     
	i = 0;               //    i      
}

//       ,         
int j = 3;
reset(j);               // j     ,    


6.3、引用を使用するメリット:メリット1:コピーを避ける.パラメータ転送では、値転送を使用すると、大きなクラスタイプやコンテナオブジェクトがコピーされる可能性があり、比較的非効率で、コピー操作がサポートされていないタイプ(IOタイプなど)もあります.パラメータを参照してのみアクセスできます.
メリット2:追加情報を返す.1つの関数は1つの値しか返されません.複数の値を同時に返す必要がある場合、参照パラメータは複数の結果を返すために有効な方法を提供します.
// find_char  ,  string                 ,      
//   s c          
//     occurs    c     
string::size_type find_char(const string& s, char c, string::size_type& occurs)
{
     
	auto ret = s.size();       //        (   )
	occurs = 0;                //         
	for (decltype(ret) i = 0; i != s.size(); ++i)
	{
     
		if (s[i] == c)
		{
     
			if (ret == s.size())
			{
     
				ret = i;       //          
			}
			occurs++;          //     +1
		}
	}
	return ret;                //       
}

7、できるだけ定数参照を使う
7.1、パラメータの初期化方式と変数の初期化方式は同じである.通常のリファレンスは、同じタイプのオブジェクトで初期化する必要があります.6.2で参照されるバージョンのresetのように、intタイプのオブジェクトしか使用できません.フォント値、評価結果がintの式、変換が必要なオブジェクト、const intタイプのオブジェクトは使用できません.定数参照ではなく参照を使用すると、関数が許容できる実パラメータタイプが大きく制限されます.定数参照を初期化するときに、任意の式を初期値として使用できることを覚えておいてください.
三、針は何ですか.
1、引用との異同:同じ点:引用と同様に、他のオブジェクトへの間接アクセスも実現した.a、ポインタ自体もオブジェクトであり、ポインタに値を付与し、コピーすることができ、異なるオブジェクトを前後して指すことができる.b、ポインタは定義に初期値を付与する必要はありません.
2、参照はオブジェクトではなく、参照を指すポインタを定義できません.
3、ポインタのタイプは、2つの例外を除いて、ポインタが指すオブジェクトと厳密に一致します.(参照と同様)
4、ポインタへの参照:ポインタはオブジェクトであり、ポインタへの参照が存在する.
int i = 22;
int *p;         // p     
int *&r = p;    // r    p   

r = &i;         // r       , r  &i   p  i
*r = 0;         //    r  i,   p     , i    0

rタイプが何であるかを判断し,rの定義を右から左に読む.変数名に最も近い記号は、変数のタイプに直接影響します.以上のように、rは参照であり、宣言子の残りの部分は、r参照のタイプが何であるかを決定するために使用され、この例では*は、r参照がポインタであることを示す.最後に、宣言された基本データ型部分は、rがint型ポインタを参照していることを示す.
5、constとポインタ
5.1.定数へのポインタ(例外1)定数参照と同様に、オブジェクトが値であることを変更することはできません.定数オブジェクトをアドレスとして保存するには、定数を指すポインタしか使用できません.定数を指すポインタは、非常に多くのオブジェクトを指すことができます.(定数を指すポインタは、constが左、*が右、constと略称)
5.2、constポインタ:ポインタのオブジェクトではなく、他のオブジェクトタイプと同様に、ポインタは自身を定数にすることができます.定数ポインタ(C++Primerのように定数ポインタを定義するのは、私たちがよく定義しているのとは逆)は初期化されなければなりません.初期化が完了すると、その値(格納されているオブジェクトへのアドレス)は変更できません.(定数ポインタは、*が左、constが右、略称*constと記すことができる).
5.3、ポインタ定数か定数ポインタか、誰もがその2人に惑わされていると信じています.中国語はその2人が迷っている主な原因です!!!直接constと*のどちらが左にいるか、どちらが右にいるかを覚えたほうがいいと思います.その2つの役割の最も良い方法は右から左へ読むことです.
int num = 12;
int *const p = #   // *const,    p    const, p     ,p         ,
                       //       *, const p     。  p  (       )     ,p          。

const int *p = #   // const*,    p     * , p     ,    p  ,
                       //      const,  *p      。  ,p  (       )    ,p           。

------------------------明日書きます(2021.05.15)-------------------------------