『データ構造とアルゴリズム』C++での参照、関数へのポインタ!


C++での参照、関数へのポインタ!
文書ディレクトリ
  • 1.参照
  • 1.1. 参照ルール
  • 1.2. C++で1つの関数にパラメータを渡す3つの方法!
  • 1.3. 参照関数としての戻り値
  • 2.関数へのポインタ
  • 2.1. 関数ポインタを関数
  • に向ける
  • 2.2. 関数ポインタによる関数呼び出し
  • 2.3. 関数ポインタの用途
  • 三.コンストラクタ初期化リスト
  • 4.参照文書
  • 一.参照
    1.1. 参照ルール
    ①参照タイプ変数を宣言する場合は、同時に初期化し、どのオブジェクトの別名、すなわちバインドオブジェクトであるかを宣言する必要があります.例:
    int &r; 	 //  ,   const  ,         
    int x, &r=x; //     r x   
    

    ②参照を空にすることはできません.参照は有効なオブジェクトのメモリセルに関連付けられている必要があります.
    ③参照が初期化されると、参照関係を変更することができず、他のオブジェクトの参照として使用することができなくなる.例:
    int x, y; //      x,y
    int &r=x; //     r x   
    int &r=y; //   r           
    

    ④指定されたタイプの参照は、他のタイプのオブジェクトに初期化できません.たとえば、次のようになります.
    double f; //       f
    int &r=f; //   r      ,            
    

    ⑤参照初期化は、参照に値を付与する意味とは全く異なります.たとえば、次のようになります.
    int x; 		//      x
    int &r=x; 	//      r x   ,  r   x
    r=100; 		//     100   r        ( x)
    

    ⑥1つの参照先を取るのと、1つのオブジェクトを取るのとは全く同じアドレスを取る演算です.例:
    int x, &r=x; 	//      x,y
    int *p1=&x; 	//p1  x
    int *p2=&r; 	//p2  r,     x
    

    1.2. C++で1つの関数にパラメータを渡す3つの方法!
    C++が参照タイプを拡張するのは、主に関数パラメータとして使用され、C++で関数にパラメータを渡すには3つの方法があります.
  • 1伝達対象自体;
  • ②オブジェクトへのポインタを渡す.
  • ③オブジェクトの参照を渡します.

  • 1オブジェクト自体を渡し、オブジェクト名で直接オブジェクトにアクセスする利点は直感的で、どのオブジェクトを操作するかが一目瞭然で、1つの関数の内部で別の関数の局所変数を使用できないという欠点がある.
    /*  ①       */
    #include <iostream>
    using namespace std;
    //        
    void swap(int a, int b)
    {
        int t;
        t = a, a = b, b = t;
    }
    int main()
    {
        int x = 10, y = 20;
        swap(x, y);
        cout << x << ", " << y << endl;
        system("pause");
        return 0;
    }
    
    10, 20
           . . .
    

    ②オブジェクト指向のポインタを渡し、ポインタ(またはアドレス)でオブジェクトに間接的にアクセスする利点は何でもできることであり、欠点はプログラムに大量に現れる間接アクセスであり、具体的にどのオブジェクトなのか分からないため、コンテキストで分析する必要がある.
    /*  ②        */
    #include <iostream>
    using namespace std;
    //        
    void swap(int *a, int *b)
    {
        int t;
        t = *a, *a = *b, *b = t;
    }
    int main()
    {
        int x = 10, y = 20;
        swap(&x, &y);
        cout << x << ", " << y << endl;
        system("pause");
        return 0;
    }
    
    20, 10
           . . .
    

    ③オブジェクトの参照を渡し、C++はC言語オブジェクトのアクセス方式を拡張し、参照アクセスを提供する.アクセスオブジェクトを参照することで、名前別アクセスとアドレス別アクセスのそれぞれの利点を組み合わせ、関数パラメータとして最適です.
    簡単に言えば、参照(reference)は、オブジェクトの別名(alias name)であり、宣言形式は次のとおりです.
         &    =     , ......;
    
      :
    int x; 	  //      x
    int &r=x; //  r x   
    

    注:C++では、参照はすべてconstタイプであり、宣言後は変更できません(つまり、他のオブジェクトの参照はできません).
    /*  ③        */
    #include <iostream>
    using namespace std;
    //        
    void swap(int &a, int &b)
    {
        int t;
        t = a, a = b, b = t;
    }
    int main()
    {
        int x = 10, y = 20;
        swap(x, y);
        cout << x << ", " << y << endl;
        system("pause");
        return 0;
    }
    
    20, 10
           . . .
    

    まとめ:明らかに、関数参照伝達方式は、ポインタ方式と同じ機能を持つ複数のデータ結果をプライマリ・コール関数に戻すことも可能である.ただし、ポインタ方式では、データの結果を返す必要があります.
  • ①実参はアドレスであり、すなわち「&」取アドレス演算を行う.
  • ②パラメータ割り当てポインタ変数は実パラメータアドレスを受け入れる.
  • ③関数内部ではポインタを使用して間接アクセス、すなわち「*」間接アクセス演算を行う.引用伝達方式はこの過程を簡略化した.

  • したがって,参照を関数パラメータとして用いることは,ポインタ変数を用いるよりも簡単で直感的で便利であり,特に被変調関数に多数のポインタが間接的にアクセスする場合,指すオブジェクトがどの具体的なオブジェクトなのかという問題を回避し,プログラミングの難易度を低減した.
    1.3. 参照関数としての戻り値
    関数の戻り値は、次の形式で定義された参照タイプ、すなわち関数の戻り参照です.
        &    (      )
    {
    	   
    }
    

    関数戻り値コード
    //  ①      
    #include <iostream>
    using namespace std;
    int max(int a, int b)
    {
        return (a > b ? a : b);
    }
    int main()
    {
        int x = 10, y = 20, z;
        z = max(x, y);
        cout << z << endl;
        system("pause");
        return 0;
    }
    
    20
           . . .
    

    関数はポインタコードを返します
    //  ②       
    #include <iostream>
    using namespace std;
    int *max(int a, int b)
    {
        return (a > b ? &a : &b);
    }
    int main()
    {
        int x = 10, y = 20, *z;
        z = max(x, y);
        cout << *z << endl;
        system("pause");
        return 0;
    }
    
    20
           . . .
    

    関数は参照コードを返します
    //  ②       
    #include <iostream>
    using namespace std;
    int& max(int &a, int &b)
    {
        return (a > b ? a : b);
    }
    int main()
    {
        int x = 10, y = 20, z;
        z = max(x, y);
        cout << z << endl;
        system("pause");
        return 0;
    }
    
    20
           . . .
    

    関数戻り参照は、一時オブジェクトを返すのではなく、エンティティオブジェクト自体を返すことに相当する関数戻り値と大きく異なります.そのため、関数は参照を左の値として返すことができます.例:
    int &fun(int &a, int &b)
    {
        return (a > b ? a : b);
    }
    int x = 10, y = 20, z = 5;
    fun(x, y) = z; //  fun      y=z;
    cout << y;
    

    二.関数へのポインタ
    関数は特定の機能を実現するプログラムコードの集合であり、実際には、関数コードはメモリにおいても記憶空間(コード領域内)を占有し、この記憶空間の開始アドレスを関数エントリアドレスと呼ぶ.
  • C++は、関数のエントリアドレスを関数とするポインタ、すなわち、関数名が関数であり、関数のポインタ(またはアドレス)であることを規定する.[ここでは配列に類比できる配列名は配列の開始アドレスを表す]
  • C++では、関数を指すポインタ変数を定義できます.定義形式は次のとおりです.
         (*       )(      ),...;
    

    次の形式の関数を指定できます.
            (      )
    {
    	   
    }
    
    int (*p)(int a, int b); //        
    

    2.1. 関数ポインタを関数に向ける
    関数ポインタを関数に向けます.
  • は、 = ;
  • の形式で、関数のアドレスを関数ポインタ変数に割り当てることができる.
  • 関数ポインタ変数は、指向関数と同じ戻りタイプ、パラメータ個数、パラメータタイプが必要です.

  • たとえば、次のように仮定します.
    int max(int a, int b);	//max    
    int min(int a, int b);	//min    
    int (*p)(int a, int b); //        
    #   :
    p = max;
    #  p    max。        min,                 、    、       。
    

    2.2. 関数ポインタから関数を呼び出す
    関数ポインタから関数を呼び出します.
  • 対の関数ポインタの間接参照は、関数ポインタによって呼び出される関数であり、一般的な形式は、 ( )
  • である.
  • は、関数ポインタを介して関数を呼び出し、実パラメータ、パラメータ伝達、戻り値などの点で関数名呼び出しと同じである.例えば、c=p(a,b); // c=max(a,b);
  • #include <iostream>
    using namespace std;
    int max(int x, int y) //  Max  
    {
        int z;
        if (x > y)
        {
            z = x;
        }
        else
        {
            z = y;
        }
        return z;
    }
    int main(void)
    {
        int a = 2, b = 3, c;
        int (*p)(int, int) = max; //          p
        // p = max;               //   Max      p,  p  Max  
        c = (*p)(a, b);           //        max  
        c = p(a, b);              //        max  ,   ,  p      ,        。
        cout << a << ", " << b << ", " << c;
        system("pause");
        return 0;
    }
    

    2.3. 関数ポインタの用途
    関数を指すポインタは、異なる関数を指すために使用されることが多く、ポインタ変数を使用して異なる関数を呼び出すことができ、関数呼び出しを静的(固定的に指定された関数を呼び出す)から動的(どの関数を呼び出すかはポインタ値によって決定される)に変更することに相当する.関数ポインタの応用を熟練して掌握して、プログラムのモジュール化の設計に有利で、プログラムの拡張性を高めます.
    三.コンストラクタ初期化リスト
    コンストラクション関数は、オブジェクトの作成時にオブジェクトを初期化し、オブジェクトデータメンバーに初期値を付与するために使用されます.
    クラスのデータ・メンバーは、クラス定義時に初期化できません.たとえば、クラス定義ではエンティティが生成されず、ストレージ領域を占有せずにデータ・タイプが与えられているため、データを格納する場所もありません.
    class Point { //Point 
    int x=0, y=0; //  ,               
    …//    
    }
    
    #include <iostream>
    using namespace std;
    
    class Cuboid //Cuboid      
    {
    public:
        Cuboid(int l, int h, int d); //      
        int volumn()
        {
            return length * heigth * depth;
        }
    
    private:
        int length, heigth, depth; // , , 
    };
    
    /*
    Cuboid::Cuboid(int l, int h, int d) //         
    {
        length = l, heigth = h, depth = d; //       
        cout << "Cuboid: "
             << "l=" << l << ", h=" << h << ", d=" << d << endl;
    }
    */
    //           
    Cuboid::Cuboid(int l, int h, int d) : length(l), heigth(h), depth(d) //         
    {
        length = l, heigth = h, depth = d; //       
        cout << "Cuboid: "
             << "l=" << l << ", h=" << h << ", d=" << d << endl;
    }
    
    int main()
    {
        Cuboid one = Cuboid(1, 2, 3);              //       a,         
        cout << "volumn=" << one.volumn() << endl; //    
        Cuboid two = Cuboid(10, 20, 30);
        cout << "volumn=" << two.volumn() << endl;
        system("pause");
        return 0;
    }
    
    Cuboid: l=1, h=2, d=3
    volumn=6
    Cuboid: l=10, h=20, d=30
    volumn=6000
           . . .
    

    四.参考記事
  • c/c++言語の宣言およびタイプをどのように理解しますか?