스타크래프트를 만들자 - 1

new는 malloc처럼 메모리를 동적으로 할당하지만, 동시에 생성자도 호출해준다.

소멸자(Destructor)

객체가 소멸 될 때 자동으로 호출되는 함수

객체를 생성할때 생성자에서 메모리 동적할당이 일어나면 그 메모리는 언제 해제해줘야 할까? 이 역할을 소멸자가 담당해준다.

소멸자는 '~클래스이름();' 으로 표현된다.

소멸자의 흔한 역할

  1. 객체가 동적으로 할당받은 메모리를 해제
  2. 쓰레드 사이에서 lock을 해제

복사자 생성자

// 복사자 생성자
T(const T& a);
T a = b;

다른 T의 객체 a를 상수 레퍼런스로 받아 복사하여 생성자를 처리하는것. 객체를 생성시에 대입하는 연산(예시의 아랫줄) 에서도 복사자 생성자를 호출한다. 또한 복사자 생성자를 생성하지 않은 경우, 디폴트 복사 생성자를 지원해주는데 대응되는 원소들을 1대1로 대응해주는 역할을 수행한다. 하지만 디폴트 복사 생성자는 값 자체를 1:1로 대응해주기 때문에, 복사자 생성자 안에서 포인터들은 모두 같은 주소를 가리키게 된다(얕은 복사). 이런 경우에는 두 객체중 한 객체만 사라져도 소멸자로 메모리가 해제되기 때문에 문제가 발생하게 된다.

// 복사 생성자의 중요성
#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(int x, int y) {
  hp = shield = 100;
  coord_x = x;
  coord_y = y;
  damage = 20;

  name = NULL;
}
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 = new char[strlen(pc.name) + 1];
  strcpy(name, pc.name);
}
Photon_Cannon::Photon_Cannon(int x, int y, const char *cannon_name) {
  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) delete[] name;
}
void Photon_Cannon::show_status() {
  std::cout << "Photon Cannon :: " << name << std::endl;
  std::cout << " Location : ( " << coord_x << " , " << coord_y << " ) "
            << std::endl;
  std::cout << " HP : " << hp << std::endl;
}
int main() {
  Photon_Cannon pc1(3, 3, "Cannon");
  Photon_Cannon pc2 = pc1;

  pc1.show_status();
  pc2.show_status();
}