[C++]Chapter 05-レプリケーションジェネレータ
05-1コピー作成者との初対面
C++スタイルの初期化
C++で変数と参照者を初期化する方法は次のとおりです.
int num = 20;
int &ref = num;
int num(20);
int &ref(num);
オブジェクトの作成に移動します.SoSimple sim2 = sim1;
SoSimple sim2(sim1);
クラス内で次のシェイプと類似シェイプを受信するにはSoSimple(SoSimple & copy)
{
}
同じ作成者が必要です.ただし、クラスにこのような作成者がいなくても、レプリケーション作成者は自動的に挿入されます.デフォルトのレプリケーション作成者(自動挿入)
レプリケーション作成者が定義されていない場合、メンバーからメンバーへのレプリケーションを行うレプリケーション作成者が自動的に挿入されます.
そして.
SoSimple sim2 = sim1;
自動SoSimple sim2(sim1);
これは「暗黙的」遷移と呼ばれる変化です.そのため、構造関数にexplicitを追加すると、「暗黙的」遷移は発生しません.explicit SoSimple(const SoSimple ©) : num(copy.num1), num2(copy.num2)
{
}
コピー作成者が参照宣言を表す&を挿入していない場合、コピー作成者の呼び出しは無限のループに陥ります.05-2「深い放射線」と「浅い放射線」
レプリケーション作成者の問題点
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:
char* name;
int age;
public:
Person(const char* myname, int myage)
{
int len = strlen(myname) + 1;
name = new char[len];
strcpy(name, myname);
age = myage;
}
void ShowPersonInfo() const
{
cout << "이름: " << name << endl;
cout << "나이: " << age << endl;
}
~Person()
{
delete[]name;
cout << "called destructor!" << endl;
}
};
int main(void)
{
Person man1("Lee dong woo", 29);
Person man2 = man1;
man1.ShowPersonInfo();
man2.ShowPersonInfo();
return 0;
}
これらのコードに問題があるのはPerson man 2=man 1が浅いコピーであり,単純なコピーであるためdeleteがman 1とman 2に適用された場合(man 2を先に削除すると仮定)、man 2はman 1を参照しているが,まずman 1の空間を削除しているため,man 1にdeleteを適用するとエラーが発生する.コードを深くコピー
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:
char* name;
int age;
public:
Person(const char* myname, int myage)
{
int len = strlen(myname) + 1;
name = new char[len];
strcpy(name, myname);
age = myage;
}
Person(const Person& person)
{
name = new char[strlen(person.name) + 1];
strcpy(name, person.name);
age = person.age;
}
void ShowPersonInfo() const
{
cout << "이름: " << name << endl;
cout << "나이: " << age << endl;
}
~Person()
{
delete[]name;
cout << "called destructor!" << endl;
}
};
int main(void)
{
Person man1("Lee dong woo", 29);
Person man2 = man1;
man1.ShowPersonInfo();
man2.ShowPersonInfo();
return 0;
}
05-3作成者のコールポイントのコピー
レプリケーション作成者には3つのコールポイントがあります
Case1
int num1 = num2;
Case2int SimpleFunc(int n)
{
....
}
int main(void)
{
int num = 10;
SimpleFunc(num); // 호출되는 순간 매개변수 n이 할당과 동시에 초기화
...
}
Case3int SimpleFunc(int n)
{
...
return n; // 반환하는 순간 메모리 공간이 할당되면서 동시에 초기화!
}
int main(void)
{
int num = 10;
cout << SimpleFunc(num) << endl;
....
}
case 3に戻ると、一時変数とオブジェクトが作成されます.一時オブジェクト
#include <iostream>
using namespace std;
class Temporary
{
private:
int num;
public:
Temporary(int n) : num(n)
{
cout << "create obj: " << endl;
}
~Temporary()
{
cout << "destroy obj:" << endl;
}
void ShowTempInfo()
{
cout << "My num is " << num << endl;
}
};
int main(void)
{
Temporary(100);
cout << "********* after make!" << endl << endl;
Temporary(200).ShowTempInfo();
cout << "********* after make!" << endl << endl;
const Temporary& ref = Temporary(300);
cout << "********* end of main!" << endl << endl;
return 0;
}
実行結果結果を説明する前に、オブジェクトのメンバー関数を呼び出すために必要な3つの項目は、次のとおりです.
上に示す結果、一時オブジェクトは次の行に進むとすぐに消えますが、参照者が参照する一時オブジェクトはすぐに消えません.
参照される一時オブジェクトの消失時間。
#include <iostream>
using namespace std;
class SoSimple
{
private:
int num;
public:
SoSimple(int n) : num(n)
{
cout << "New Object: " << this << endl;
}
SoSimple(const SoSimple& copy) : num(copy.num)
{
cout << "New Copy obj: " << this << endl;
}
~SoSimple()
{
cout << "Destroy obj:" << this << endl;
}
};
SoSimple SimpleFuncObj(SoSimple ob)
{
cout << "Parm ADR: " << &ob << endl;
return ob;
}
int main(void)
{
SoSimple obj(7);
SimpleFuncObj(obj);
cout << endl;
SoSimple tempRef = SimpleFuncObj(obj);
cout << "Return Obj" << &tempRef << endl;
return 0;
}
実行結果SoSimple obj(7)を実行するのは初めてです.オブジェクトはreturn 0(すなわち、関数が終了する前に作成され、消えます).したがってtemprefが参照するオブジェクトの消失はtemprefが関数を終了する時点である.
ここで、temprefは他のオブジェクトを作成せず、一時オブジェクトに名前を割り当てるだけです(オブジェクトの作成数を減らすことで効率が向上します)-->temprefは一時オブジェクトのアドレス値と同じです.
Reference
この問題について([C++]Chapter 05-レプリケーションジェネレータ), 我々は、より多くの情報をここで見つけました https://velog.io/@hustle-dev/C-Chapter-05-복사-생성자テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol