定理によれば、配列を別の配列のコピーとして初期化することはできません。ただし、別の配列の最初の要素を指すポインターのコピーとしてポインターを初期化できます。
int a[] = {0, 1, 2};
int a2[] = a; //error
int *a3 = a; //OK
なぜint a2[] = a;
エラーなのですか?
定理によれば、配列を別の配列のコピーとして初期化することはできません。ただし、別の配列の最初の要素を指すポインターのコピーとしてポインターを初期化できます。
int a[] = {0, 1, 2};
int a2[] = a; //error
int *a3 = a; //OK
なぜint a2[] = a;
エラーなのですか?
配列はCでできないため、C ++で別の配列オブジェクトに割り当てたり、初期化したりすることはできません。また、歴史的な理由からCで配列を作成することはできません。これは、もはや実際には関係ありません。
非常に初期のproto-Cでは、のような割り当てint a[] = {0}; int b[] = {0}; a = b;
で配列の内容をにコピーするか、参照する名前を再設定b
するかについて、混乱が生じる可能性があります。初期化の場合と同様に、のコピーであるかエイリアスであるか。このあいまいさは40年間存在していません。許可された場合、C(およびC ++)での意味はコピーする必要があるという意味であることがすぐに明らかになりましたが、Cの配列は「適切な」値にはなりませんでした。タイプ。a
a
b
a
b
それが不可能であるという技術的な理由はありません。たとえば、データメンバーとして配列を持つ構造体タイプを割り当てることができます。この標準では、コードが正しいC++であると定義されていません。
ポインタの動作は、これに直接関係していません。ポインターの初期化(配列の最初の要素を指す)は、配列とその内容の初期化とは異なる操作であり、言語はRHSでさまざまなことを許可します。
配列はポインターではないため、問題が発生しない限り、配列をポインターのように使用することは期待できません。違いを学ぶのに役立つアクティビティについては、https://blogs.oracle.com/ksplice/entry/the_ksplice_pointer_challengeにアクセスしてください。
配列を構造体でラップすると、配列を別の配列のコピーとして初期化できます。
struct myarray {
int a[3];
};
コンパイラがGNUC++スタイル指定の初期化子を許可する場合:
myarray a = {a: {0, 1, 2}};
これにより、a2の配列への配列を含む構造体のコピーが実行されます。
myarray a2 = a;
アレイはメモリ内のさまざまな場所に配置されます。
bool is_different_array = a2.a != a.a; // true
ある配列を別の配列に割り当てることは可能ですが、最初の配列の基になるデータを2番目の配列にコピーすることによってのみ可能です(たとえば、ループを使用)。質問のコード行:
int *a3 = a;
a3
配列の最初の要素のアドレスを指すように呼び出されたポインターを割り当てるだけですa
が、これら2つの変数が参照する基になるデータ(この場合は整数)は変更されません。
また、配列とポインタの関係については、こちらを確認してください。
配列は単なるポインタではありません。この例では、配列a[]
は3つの整数サイズの連続したメモリアドレスがメモリに予約されていることを表しています。その配列を「コピー」しようとすると、3つの整数サイズの連続したメモリアドレスを予約0 1 2
して、それらにコピーする必要があります。プリミティブの代入演算子は、これほど多くの作業を行うことは期待されていません。
ただし、ポインタを作成するときは、の場所に名前を付けるだけですa[]
。
あなたがこれをするなら
int *a3 = a;
値をコピーするのではなく、ポインタと呼ばれるメモリアドレスだけをコピーします
配列の値をコピーしない場合は、コピーコンストラクターを定義する必要があります。
別の方法で見てみましょう。配列は、C /C++の静的割り当てで機能します。したがって、コンパイラがコンパイル時に配列のサイズを把握できることを確認する必要があります。これは、非常に多くの理由から、配列の必須条件です。したがって、コンパイラが「[]」表記に遭遇するたびに、メモリサイズ(実行時に割り当てる必要がある)がコード自体から計算できることを期待します。
C / C ++で配列を定義すると、配列のメモリが割り当てられます(配列とは、配列要素が格納されるセルを意味します)。今あなたが好きと言うとき
int a[] = {3,4,5,6};
いくつかのメモリ、たとえば4つの要素に16バイトを割り当てます。これは、コンパイル時にコンパイラによって計算されます。
今あなたが言うとき
int a2[] = a;
コンパイラは配列表記'[]'を認識しますが、配列セルに割り当てる必要のあるメモリの量を識別できないため、エラーが発生します。
配列について話すとき、それは常に定数ポインターによってポイントされる逆参照セルについてですが、ポインターについて話すとき、それは何も参照せずに存在することができます。これはダングリングポインターとして知られています。それが役に立てば幸い。
スタックに割り当てられる配列を宣言する場合、コンパイラは要素の数を知っている必要があります。そのため、次のように宣言する必要があります。
int a[] = {x,y,etc..};
また
int a[NUMELEMENTS];
既存の配列を指すポインターを持つことは許容されますが、既存の配列へのポインターから新しいスタック配列を作成することはできません。これはint a2[]= a;
、実行しようとしていることです。コンパイラは、a2に割り当てる要素の数を知りません。
通常、配列を別の配列にコピーする最良の方法は、を使用することstd::copy
です。