C++の配列メンバーはディープコピーされる?構造体・クラス代入の仕組みを解説
C/C++では、同じ型の構造体変数(C++ではクラスのオブジェクトも同様)を、別の変数に代入することができます。この代入が行われると、元の変数のすべてのメンバーが相手側の構造体変数へコピーされます。ここで一つ疑問が生じます。「構造体が配列をメンバーとして持っている場合、その配列はどのようにコピーされるのか?」という点です。
結論から述べると、配列メンバーはシャローコピー(浅いコピー)ではなく、コンパイラが自動的にディープコピー(深いコピー)を行います。次のプログラムでは、構造体 test が配列メンバー str1[] を持っています。st1 を st2 に代入すると、st2 は配列のまったく新しいコピーを獲得します。そのため、st1 側の配列の内容を後から書き換えても、st2 の配列には一切影響しません。
サンプルコード
# include <iostream>
# include <string.h>
using namespace std;
struct test{
char str1[20];
};
int main(){
struct test st1, st2;
strcpy(st1.str1, "Tutorial Point");
st2 = st1;
st1.str1[0] = 'X';
st1.str1[1] = 'Y';
/* コピーはディープコピーのため、両者の配列は別物 */
cout<< "st1のstr = " << st1.str1 << endl;
cout<< "st2のstr = " << st2.str1 << endl;
return 0;
}
実行結果
st1のstr = XYtorial Point st2のstr = Tutorial Point
実行結果を見ると、st1 の文字列の先頭2文字を「XY」に書き換えても、st2 の文字列は元の「Tutorial Point」のまま維持されていることが分かります。これは、両者の配列がメモリ上で完全に独立していることの証拠です。
したがって、C++のクラスにおいて、配列メンバーのために独自のコピーコンストラクタやコピー代入演算子を定義する必要はありません。配列に対するデフォルトのコピー動作が、すでにディープコピーになっているためです。
ただし注意したいのはポインタメンバーの場合です。デフォルトのコピーでは、ポインタが保持するアドレスの値のみが複製され、参照先の実体は両者で共有されてしまいます(シャローコピー)。これにより二重解放などの不具合を招く恐れがあるため、ポインタメンバーを持つクラスでは自前のコピーコンストラクタと代入演算子を実装するか、std::string や std::vector などのコンテナを利用するのが安全です。
-
C++で配列を並べ替える方法|選択ソートの仕組みと実装例を解説
C++では、さまざまなソート(並べ替え)アルゴリズムを使って配列を整列できます。ソート済みの配列とは、数値の大小順やアルファベット順など、何らかの基準に従って要素が並び替えられた配列のことです。代表的なソートアルゴリズムには、バブルソート、挿入ソート、選択ソート、マージソート、クイックソート、ヒープソートなどがあります。本記事では、その中でも構造がシンプルで理解しやすい「選択ソート」を取り上げ、実際のコード例とともに詳しく解説していきます。 選択ソートとは? 選択ソートは、未ソート部分の中から最小値を繰り返し探し出し、それを未ソート部分の先頭にある要素と交換することで、配列全体を昇順に整列さ
-
【C++入門】静的クラスメンバーはいつ初期化される?仕組みとサンプルコードを解説
静的クラスメンバーとは C++では、staticキーワードを使ってクラスに静的メンバー(スタティックメンバー)を定義できます。静的メンバーは特定のオブジェクトに属するのではなく、クラスそのものに紐づくメンバーです。 メモリ上には静的メンバーのコピーが1つだけ存在するため、オブジェクトをいくつ生成しても、すべてのオブジェクトが同じ値を共有します。オブジェクト間で共通のカウンタや設定値を管理したい場合などに非常に便利な仕組みです。 静的メンバーが初期化されるタイミング 静的クラスメンバーは、他の方法で明示的に初期化しない場合でも、自動的にゼロで初期化されます。静的記憶域期間を持つ変数は、プログラ