이번 시간에는 포인터의 개념중에서 얕은복사, 깊은 복사에 대해서 알아보겠습니다.
#include <string.h>
#include <iostream>
class Photon_Cannon
{
int hp, shield;
int coord_x, coord_y;
int damage;
char *name;
public:
Photon_Cannon(int x, int y);
Photon_Cannon(int x, int y, const char *cannon_name);
Photon_Cannon(const Photon_Cannon &pc);
~Photon_Cannon();
void show_status();
};
Photon_Cannon::Photon_Cannon(const Photon_Cannon &pc)
{
std::cout << "복사 생성자 호출 !" << std::endl;
hp = pc.hp;
shield = pc.shield;
coord_x = pc.coord_x;
coord_y = pc.coord_y;
damage = pc.damage;
// 얕은복사
name = pc.name;
// 깊은복사
// name = new char(strlen(pc.name) + 1);
// strcpy(name, pc.name);
}
Photon_Cannon::Photon_Cannon(int x, int y)
{
std::cout << "생성자 호출 !" << std::endl;
hp = shield = 100;
coord_x = x;
coord_y = y;
damage = 20;
name = NULL;
}
Photon_Cannon::Photon_Cannon(int x, int y, const char *cannon_name)
{
std::cout << "(name)생성자 호출 !" << std::endl;
hp = shield = 100;
coord_x = x;
coord_y = y;
damage = 20;
name = new char(strlen(cannon_name) + 1);
strcpy(name, cannon_name);
}
Photon_Cannon::~Photon_Cannon()
{
if (name)
{
std::cout << name << " destruct called !" << std::endl;
delete[] name;
}
}
void Photon_Cannon::show_status()
{
std::cout << std::endl;
std::cout << "Photon Cannon STATUS" << std::endl;
std::cout << " Location : ( " << coord_x << " , " << coord_y << " ) "
<< std::endl;
std::cout << " HP : " << hp << std::endl;
std::cout << " HP : " << &hp << std::endl;
printf(" HP's address : %p\n", &hp);
std::cout << " Name : " << name << std::endl;
std::cout << " Name : " << &name << std::endl;
printf(" Name's address : %p\n", name);
}
int main()
{
Photon_Cannon pc1(3, 3, "cannon");
Photon_Cannon pc2 = pc1;
pc1.show_status();
pc2.show_status();
std::cout << &pc1 << std::endl;
std::cout << &pc2 << std::endl;
}
아래 내용은 복사 생성자입니다. 복사 생성자를 만들때, 얕은 복사를 한 경우의 문제점을 보기 위한 코드립니다.
얕은 복사를 하면 2개의 변수(name)가 같은 메모리를 참조합니다. 그래서 메모리 free 할때 오류가 발생한다.
Photon_Cannon::Photon_Cannon(const Photon_Cannon &pc)
{
std::cout << "복사 생성자 호출 !" << std::endl;
hp = pc.hp;
shield = pc.shield;
coord_x = pc.coord_x;
coord_y = pc.coord_y;
damage = pc.damage;
// 얕은복사
name = pc.name;
// 깊은복사
// name = new char(strlen(pc.name) + 1);
// strcpy(name, pc.name);
}
아래 내용은 복사 생성자를 만들때 주의해야하는, 얕은 복사를 할때 발생하는 오류 로그입니다.
2개의 객체에 대한 각각의 소멸자가 호출될때 첫번째 객체의 소멸자는 정상적으로 메모리 해제를 실행했는데,
두번째 객체의 소멸자가 메모리 해제를 실행하려고 하니 이미 해당 메모리는 해제가 되었다고 오류 메시지를 출력합니다.
아래 내용은 이전 복사 생성자를 수정하여 입니다. 복사 생성자를 만들때, 얕은 복사를 한 경우의 문제점을 보기 위한 코드립니다.
깊은 복사를 통해서 메모리 free 할때 오류 문제를 해결한 코드입니다.
Photon_Cannon::Photon_Cannon(const Photon_Cannon &pc)
{
std::cout << "복사 생성자 호출 !" << std::endl;
hp = pc.hp;
shield = pc.shield;
coord_x = pc.coord_x;
coord_y = pc.coord_y;
damage = pc.damage;
// 얕은복사
// name = pc.name;
// 깊은복사
name = new char(strlen(pc.name) + 1);
strcpy(name, pc.name);
}
name 변수의 메모리 주소가 다른 메모리를 참조하는것을 볼 수 있다.
참고자료 : "모두의 코드" 사이트.
'C++' 카테고리의 다른 글
[C++] 상속(inheritance) - protected, private 키워드 (0) | 2023.02.16 |
---|---|
[C++] 상속(inheritance) (0) | 2023.02.16 |
[C++] 포인터 - 연산자 오버로딩(overloading) (0) | 2023.02.14 |
[C++] 포인터 - 얕은복사/깊은복사(샘플3), 생성자, 소멸자 (0) | 2023.02.03 |
[C++] 포인터 - 얕은복사/깊은복사(샘플2) (0) | 2023.02.03 |