얕은 복사와 깊은 복사

이승덱·2021년 7월 21일

CPP

목록 보기
38/70
#include <iostream>

#include<iomanip>

using namespace std;

//얕은 복사 vs 깊은 복사

class Pet{

public:

public:

 Pet() {

 cout << "Pet()" << endl;

 }

 ~Pet() {

 cout << "~Pet()" << endl;

 }

 Pet(const Pet& pet) {

 cout << "Pet(const Pet&)" << endl;

 }

};

class RabbitPet :public Pet {

};

class Knight {

public:

 //Knight와 Pet의 생명주기를 같다고 가정해보자

 Knight() {

 _pet = new Pet();

 }

 //깊은 복사를 위해 복사생성자, 복사 대입 연산자를 직접 정의해야함

 Knight(const Knight& knight) {

 _hp = knight._hp;

 _pet = new Pet(*knight._pet); //깊은 복사

 }

 Knight& operator=(const Knight& knight) {

 _hp = knight._hp;

 _pet = new Pet(*knight._pet); //깊은 복사

 return *this;

 }

 ~Knight() {

 delete _pet;

 }

public:

 int _hp = 100;

 //Pet _pet; //펫의 데이터를 모두 나이트가 가지게 됨

 Pet* _pet;  //따라서 펫의 포인터를 들고있게 하는 것이 효율적

};

int main()

{

 Knight knight; //기본 생성자

 knight._hp = 200;

 Knight knight2 = knight; //복사 생성자

 //Knight knight3(knight);

 

 

 Knight knight4; //기본 생성자

 knight4 = knight; //복사 대입 연산자

 // [복사 생성자] + [복사 대입 생성자]

 // 둘 다 안 만들어주면 컴파일러가 '암시적으로' 만들어줌.

 // 중간 결론) 컴파일러가 알아서 잘 만들어준다?

 // =>직접 만들어야 할 경우가 생긴다

 //[ 얕은 복사 Shallow Copy ]

 //멤버 데이터를 비트열 단위로 '똑같이' 복사 (메모리 영역 값을 그대로 복사)

 //포인터는 주소값 바구니 -> 주소값을 똑같이 복사 -> 동일한 객체를 가리키는 상태가 됨

 //Stack : Knight [ hp,  0x1000 ] -> Heap 0x1000 Pet[ ] <- 첫번째 나이트의 상황

 //Stack : Knight2 [ hp,  0x1000 ] 

 //Stack : Knight3 [ hp,  0x1000 ] 

 //Stack : Knight4 [ hp,  0x1000 ] 모두 같은 Pet의 주소를 공유하게 된다.

 //같은 Pet을 공유하므로 Double Free가 되버림

 //[ 깊은 복사 Deep Copy ]

 //멤버 데이터가 참조(주소) 값이라면, 데이터를 새로 만들어준다(원본 객체가 참조하는 대상까지 새로 만들어서 복사)

 //포인터는 주소값 바구니 -> 새로운 객체를 생성 -> 상이한 객체를 가리키는 상태가 된다.

 //Stack : Knight [ hp,  0x1000 ] -> Heap 0x1000 Pet[ ] <- 첫번째 나이트의 상황

 //Stack : Knight2 [ hp,  0x2000 ] -> Heap 0x2000 Pet[ ] <- 두번째 나이트의 상황

 //Stack : Knight3 [ hp,  0x3000 ] -> Heap 0x3000 Pet[ ] <- 세번째 나이트의 상황

 return 0;

}
profile
공부 기록용 블로그입니다

0개의 댓글