[C++]浅い放射と深い放射
コンセプト
既存のオブジェクトのコピーを作成します.
たとえば、AオブジェクトをBオブジェクトにコピーします.最も一般的なのは、
Widget B = A;
のようなコピージェネレータなどによってAをBにコピーすることができることである.しかし、問題もある.
簡単に言えば、コピーは、元のオブジェクト(A)のすべてのフィールド属性をコピーするために、初期化されていない新しいオブジェクト(B)を割り当てることによって実現される.
複雑な場合(参照値がコピーされている場合)、結果は必要な操作に合致しません.
これらの違いにより、浅いコピーと深いコピーの概念が現れます.
左の浅いコピー、pとqはメモリを指します.
右側の深いコピーは、pとqの異なるメモリをコピーします.
ここではp,qをポインタとしてもよい.
浅いコピー
Widget B = A;
は、新しいオブジェクトBを作成し、Aのフィールド値をBにコピーします.このように参照されるオブジェクトは共有され、AまたはBのいずれかが変更されると、もう一方も変更されます.(同じメモリアドレスを共有)
深くコピー
例
複製生成者の動作は以下と類似していると推測される.
nameは浅いコピーが発生しています(rhs.nameのアドレス値を加算します).
その結果,予想と異なりnameはrhsであった.nameの「アドレス」を参照しています.
rhsオブジェクトが何らかの理由で消えた場合、nameが指すアドレスは有効ではありません.
class ShallowCopyExam
{
public:
int age;
char* name;
ShallowCopyExam(const ShallowCopyExam& rhs)
{
age = rhs.age;
name = rhs.name;
}
...
};
深度レプリケーションを実現するには、レプリケーションジェネレータを直接作成します.
strcpy()メソッドにより、nameではrhsのみが使用されます.nameのアドレス値、rhsは入力しません.nameを一時オブジェクトにコピーし、一時オブジェクトの値(文字)をnameにコピーします.
class DeepCopyExam
{
public:
int age;
char* name;
DeepCopyExam(const DeepCopyExam& rhs)
{
age = rhs.age;
name = new char[strlen(rhs.name) + 1];
// 단순히 주소값을 넣어주는 것이 아니라
// rhs.name의 값을 name에 복사하고 있다.
strcpy(name, rhs.name);
}
...
};
サンプルコード
#include <iostream>
#pragma warning(disable:4996)
using namespace std;
class ShallowCopyExam
{
public:
int age;
char* name;
ShallowCopyExam(int _age, const char* _name)
{
age = _age;
name = new char[strlen(_name) + 1];
strcpy(name, _name);
}
/*
* 디폴트 복사 생성자는 아래와 비슷하게 동작하고 있을 것이라고 짐작이 가능하다.
* name에 얕은 복사(rhs.name의 주소값을 넣어줌)가 일어나고 있다.
* 결과적으로 의도한 바와 다르게 name 이 rhs.name 의 '주소'를 참조하고 있다.
* 어떤 이유에서 rhs 객체가 소멸한다면 name 이 가리키는 주소는 더이상 유효하지 않게 될 것이다.
ShallowCopyExam(const ShallowCopyExam& rhs)
{
age = rhs.age;
name = rhs.name;
}
*/
void infoPerson()
{
cout << "이름: " << name << ", ";
cout << "나이: " << age << endl;
}
};
class DeepCopyExam
{
public:
int age;
char* name;
DeepCopyExam(int _age, const char* _name)
{
age = _age;
name = new char[strlen(_name) + 1];
strcpy(name, _name);
}
// 복사 생성자 - 깊은 복사
// 깊은 복사를 위해 복사 생성자를 직접 작성해준다.
DeepCopyExam(const DeepCopyExam& rhs)
{
age = rhs.age;
name = new char[strlen(rhs.name) + 1];
// 단순히 주소값을 넣어주는 것이 아니라
// rhs.name의 값을 name에 복사하고 있다.
strcpy(name, rhs.name);
}
void infoPerson()
{
cout << "이름: " << name << ", ";
cout << "나이: " << age << endl;
}
};
int main()
{
// ---------------------얕은 복사---------------------
ShallowCopyExam human3(30, "세종");
ShallowCopyExam human4 = human3; // 디폴트 복사 생성자가 호출된다.
human4.age = 33;
strcpy(human4.name, "단군");
cout << "<얕은 복사>" << endl;
human3.infoPerson(); // 이름: 단군, 나이: 30
human4.infoPerson(); // 이름: 단군, 나이: 33
// ---------------------깊은 복사---------------------
DeepCopyExam human1(20, "홍길동");
DeepCopyExam human2 = human1; // (깊은) 복사 생성자가 호출된다.
human2.age = 22;
strcpy(human2.name, "이순신");
cout << "<깊은 복사>" << endl;
human1.infoPerson(); // 이름: 홍길동, 나이: 20
human2.infoPerson(); // 이름: 이순신, 나이: 22
}
しゅつりょく
<얕은 복사>
이름: 단군, 나이: 30
이름: 단군, 나이: 33
<깊은 복사>
이름: 홍길동, 나이: 20
이름: 이순신, 나이: 22
リファレンス
Wikipedia-複製対象
ゼタウィキ-浅い放射、深い放射
すべてのコードC言語参照-strcpy関数
Reference
この問題について([C++]浅い放射と深い放射), 我々は、より多くの情報をここで見つけました https://velog.io/@hhj3258/C-얕은-복사와-깊은-복사テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol