配列と参照をパラメータと戻り値として渡すことを理解する


根本:配列はコピーできないため、関数、戻り値が配列変数を渡すのは配列のポインタまたは参照のみです.
  
一、関数戻り値問題:ポインタ(注:関数の戻り値は配列ではなく、配列のポインタまたは参照のみ)
1、関数戻りポインタ(動的配列を含む)
宣言:int*retArray(int i);
宣言:int*retArray(int i)[10];関数は配列を返し、内部には基本データ型のポインタが格納されます.
注意:この定義は間違っています.関数の戻り値は配列が禁止されており、配列ポインタまたは参照のみで使用できます.
2、関数の戻り値は固定サイズの配列ポインタであり、配列に格納されたデータは基本データ型である
宣言:int(*retArray(int i))[10];//この関数は配列内部intの10サイズ配列ポインタを返します
定義:
int (*retArray(int i))[10]
{
    static int a[10] = {1};
    return &a;   //         []   ,    &    
}
3、関数の戻り値固定サイズの配列ポインタ、配列格納データが基本データ型のポインタ
宣言:int*(*retArray(int i))[10];
定義:
int *(* retArray(int i))[10]
{
    int *a[10];
    for(int i = 0;i<10;i++)
    {
        a[10] = &i;  //              
    }
    return &a;
} 

二、関数戻り値問題:引用
1、関数は参照を返す
宣言:int&retArray(int i);この宣言は、基本データ型を返す変数としてのみ使用でき、配列を返すことはできません.
int&retArray(int i)[10];関数は配列を返し、基本データ型の参照を内部に格納します.
注意:この定義はエラーです.関数の戻り値は配列が禁止されています.配列ポインタまたは参照のみで、参照配列の定義はエラーです.
2、関数の戻り値は固定サイズの配列参照であり、配列格納データは基本データ型である
宣言:int(&retArray(int i))[10];
定義:
int (& retArray(int i))[10]
{
    int a[10] = {1};
    return a;
{ 
3、関数の戻り値は固定サイズの配列参照であり、配列内部のデータ型は基本データ型の参照である
宣言:int&(&retArray(int i))[10];
エラー:配列内部に参照タイプデータを格納することは許可されません.
三、関数戻り値問題:ポインタ、参照混合
1、定義:int*(&retArray(int i))[10];
宣言:
int *(& retArray(int i))[10]
{
    int *a[10];
    for(int i=0;i<10;i++)
    {
        a[i] = &i;
    }
    return a;
}
2、定義:int&(*retArray(int i))[10];
エラー:内部を参照タイプとして定義しない配列
四、関数戻り値利用型別名
1、タイプ別名定義戻り値タイプ
using array = int [10];   typedef int array[10]    //  array  
array * retArray(int i);   //        10        
array & retArray(int i);   //      10        
、decltype定義戻り値タイプ
int array[] = {1,2,3,4,5,6,7,8,9,0}
decltype(array) * retArray(int i);  //        10        
decltype(array) & retArray(int i);  //      10        
3、テールタイプ使用
  • ポインタ:
  • 宣言:auto retArray(int i)->int(*)[10];//関数retArray整形パラメータiを受け入れ、int型配列ポインタを返す
    宣言:auto retArray(int i)->int*(*)[10];//関数retArray整形パラメータiを受信し、int*型配列ポインタを返す
    宣言:auto retArray(int 0)->int[10];//エラー、関数は配列に直接戻ることはできません
  • 参照:
  • 宣言:auto retArray(int i)->int&;//整形変数の参照を返す
    宣言:auto retArray(int i)->int(&)[10];//整形配列の参照を返す
    宣言:auto retArray(int i)->int&[10]//参照配列を返すことは許可されません
  • ポインタ、参照ブレンド:
  • 宣言:auto retArray(int i)->int*(&)[10];//ポインタ配列の参照を返す
    宣言:auto retArray(int i)->int&(*)[10];//参照配列を戻すことはできません
    五、配列をパラメータとして渡す.
    宣言された配列がポインタ配列(int(*)[])または参照配列(int(&)[])である場合、配列のサイズを指定する必要があります.
    1、ポインタ
  • ポインタ(暗黙配列を含み、ポインタのポインタは類似している)宣言:int retArray(int*i);

  • 呼び出し:
    int *i = nullptr;
    retArray(i);
  • 配列ポインタ
  • 宣言:int retArray(int(*i)[10]);//形パラメトリック指定サイズ
    宣言:
    template    //     ,    
    void retArray(int (*i)[T],int (*j)[U])
    コール:
    int (*arr)[10];
    retArray(arr);                
    
  • 配列は、基本データ型ポインタ
  • として記憶する.
    宣言:int retArray(int*i[]);//パラメータ配列サイズを明示的に指定する必要はありません
    呼び出し:
    int *arr[10];
    for (int i;i<10;++i)
    {
        arr[i] = & i;  //             
    }
    retArray(arr);
  • 配列内部には、基本データ型ポインタが格納、この配列
  • を参照する.
    宣言:int retArray(int*(*i)[10])/配列サイズを明示的に指定する必要があります
    宣言:
    template
    int ret(int *(*i)[T])
    コール:
    int * (*arr)[10] = nullptr;
    retArray(arr);

    2、引用:
  • 基本データ型参照
  • 定義:int retArray(int&a);//配列はポインタ(正確な一致)に変換できるので、実際にはポインタが伝達されます
    呼び出し:
    int a =10;
    retArray(a);
  • 基本データ型配列の参照
  • 定義:int retArray(int(&a)[10]);//ここでパラメータは明示的にサイズを指定する必要があります
    定義:
    template    //     ,    
    int retArray(int (&a)[T],int (&b)[U])
    コール:
    int arr[10] = {1};
    retArray(arr);                   
    
  • 基本データ型参照配列の参照
  • 定義:int retArray(int&(&a)[10]);   
    エラー:内部で基本データ型として参照される配列を定義することは禁止されています.
    3、ポインタ、参照ブレンド
  • 基本データ型ポインタの配列参照
  • 定義:int retArray(int*(&a)[10]);//配列ポインタまたは配列参照はサイズのみを指定する必要があります
    定義:
    template
    int ret(int * (&a)[T]);
    コール:
    int *arr[10];
    retArray(arr);
  • 基本データ型参照配列ポインタ
  • 定義:int retArrar(int&(*a)[]);
    エラー:基本データ型の参照を定義する配列は禁止されています.
    4、注意
  • 配列ポインタが関数パラメータである場合:
  • ポインタはメモリを指す変数として、実パラメータとしてパラメータに渡されるとき.メモリには、ポインタパラメータ変数の空間も申請され、変数から変数へのコピーの問題に関連する変数空間アドレスが格納されます.ただし、実関与パラメータが指すメモリ空間は一致しており、パラメータによって実パラメータが指す空間数値を変更することができる.したがって,関数内部でパラメータが格納する変数値(すなわち変数アドレス)を変更し,その新しい変数をパラメータが指し示すに任せても,実パラメータの指し示すアドレス値は変更されないが,実パラメータが空間変数を指す場合(実参加パラメータが同じアドレスを指すことを前提とする)を変更すると,実パラメータが指し示す空間変数値も変更される.
  • ポインタのポインタを定義するとき:
  • int **p    int *q[constant];
    特に注意してください.
    p,q変数の記憶空間定義は初期化され、その初期指向アドレスは0 x 0000である.ポインタ変数はアドレス値:0 x 0000;
    q配列内部には空間が割り当てられており、記憶はすべて0 x 0000(0 x 0000を指す)であり、その内部空間はint*を指す変数として記憶しなければならないが、配列内部ポインタが指す空間は指向していない.
    pは明示的な空間を指していませんが、コンパイラはデフォルトで0 x 0000空間(予約空間、読み書き権限なし)を指し、ポインタ値は0 x 0000として格納されます.
    pが2つの空間値を指すことに注意してください.
    p = (int **)malloc(sizeof(int));
    *p = (int *)malloc(sizeof(int));
  • ポインタ変数アドレス問題:
  • int a = 1;
    int *pointB = &a;
    int *pointC = &a;
    //pointB pointC       a    ,        
    cout << pointB;
    cout << pointC;
    //            
    //    pointB pointC              ,             
    cout << &pointB;
    cout << &pointC;
    //             

    一言:ポインタがパラメータとして渡されるとコピーが存在し、ポインタ変数が格納するアドレス値コピーの問題に関連する.ポインタも基本データ型で、メモリにスペースを消費します