About C++ – “생성자, 소멸자”

About C++ – “생성자, 소멸자”

2021/11/10 3:07 PM

생성자와 소멸자의 개념

  • 생성자와 소멸자는 멤버함수입니다. 하지만, 사용자가 꼭 정의하지 않아도 됩니다.
  • 정의하지 않는 것이라고 해서 존재하지 않는 것은 아니며 시스템 내부에서 객체의 생성, 소멸을 담당합니다.
  • 사용자가 이를 조금 더 유용하게 사용하고자 하는 경우, 가시화시켜 클래스 내부에 선언하고 정의할 수 있습니다.

생성자란?

int num1 = 500; 의 코드는 무엇을 의미할까요, 모두들 아시겠지만 이것은 메모리에 int형 기억장소 4바이트를 메모리에 할당한 다음, 그 곳에 500이라는 초깃값을 주는 것입니다. 이처럼 char, float 등의 일반 자료형들의 경우 컴파일러가 알아서 그 동작을 수행합니다.

하지만 클래스의 경우에는 그것을 사용자가 정의합니다. 그러한 경우에는 어떻게 객체를 초기화할까요? 바로 생성자가 그 역할을 담당합니다. 생성자는 사용자가 특별히 지정하지 않아도 자동으로 호출이 되지만, 멤버에 대한 초기화 자료를 지정하지 않으면 가비지 값을 가지게 됩니다. 생성자는 멤버변수의 초기화를 담당하는 역할을 합니다.

#include <iostream>
using std::cout;
class Dog {
  private:
    int age = 13;
    //int age; 로 끝내면..
  public:
    int getAge();
    void setAge(int a);
};

int Dog::getAge()
  {return age;}
void Dog::setAge(int a)
  {age = a; }

int main()
{
  Dog happy,coco;
  cout << "happy나이 : " <<happy.getAge()<<"\n"
  << "coco나이 : " <<coco.getAge();
  return 0;
}

//happy나이 : 0
//coco나이 : -117735264 
//초깃값을 제공하지 않으면, 가비지 값을 가집니다.

생성자의 예시 코드입니다. 이 경우에서 멤버에 대한 초기화 값을 제공하지 않으면, 가비지 값이 나올 것입니다.

생성자는 다음의 특징을 가집니다.

  • 생성자의 이름은 클래스명과 같습니다.
  • 클래스의 객체가 생성될 때마다, 자동으로 호출됩니다. – 사용자가 호출할 수 없습니다.
  • 객체가 메모리에 할당될 때 멤버 변수의 초기화를 담당합니다.
  • 리턴형을 쓰지 않습니다.
  • 하나의 클래스에 여러 개의 생성자가 존재할 수도 있습니다.
  • 생성자가 반드시 있어야 하는 것은 아니지만, 메모리를 초기화한다는 의미에서 있는 것이 좋습니다.
#include <iostream>
using std::cout;

class Fish{
  private:
    float length;
  public:
    Fish(){length = 24.3;} // 생성자를 정의했습니다.
    float getLength(){return length;}
    void setLength(float a){length = a;}
};

int main()
{
  Fish discus;
  cout<<discus.getLength();
  return 0;
}

이러한 식으로 생성자를 정의해서, private 멤버변수인 length의 초깃값을 넣을 수 있습니다.

소멸자란?

  • 소멸자는 클래스의 객체가 소멸될 때 자동으로 호출됩니다.
  • 이름은 클래스명과 같으며 앞에 “~”를 붙이면 됩니다.
  • 하나의 클래스에 하나만 존재합니다.
  • 리턴형과 매개변수가 없습니다.
  • 생성자와 마찬가지로, 사용자가 직접 호출할 수 없습니다.
  • 객체가 소멸될 때 자동으로 호출되는 특징이 있기에, 객체가 소멸될 때 동작했으면 하는 코드를 삽입합니다.
  • 소멸자는 사용한 메모리 공간이 더 이상 불필요하게 될 때, 해당 메모리를 시스템이나 다른 객체에 반납하는 용도로 많이 사용합니다.
#include <iostream>
using std::cout;

class Fish{
  private:
    int length;
  public:
    Fish(int a){length = a; cout<<"뻐끔뻐끔...\n";}
    //생성자를 정의했습니다.
    ~Fish(){cout<<"소멸되었음!!!\n";}
    //소멸자를 정의했습니다.
  int getLength();
  void setLength(int a);
};

int Fish::getLength()
{
  return length;
}

void Fish::setLength(int a)
{
  length = a;
}

int main()
{
  Fish guppy(5); // 초기화
  cout<<"메인함수가 시작됩니다...\n";
  cout<<guppy.getLength();
  cout<<"\n메인함수가 끝났습니다...\n";
  return 0;
}

//뻐끔뻐끔...
//메인함수가 시작됩니다...
//5
//메인함수가 끝났습니다...
//소멸되었음!!!

코드를 보고, 결과가 왜 그렇게 나오는지 이해해 봅시다. 생성자를 “뻐끔뻐끔”을 출력하도록 하였기 때문에 fish guppy(5)로 객체가 생성되는 순간 “뻐끔뻐끔”이 가장 먼저 출력되는 것을 볼 수 있습니다.

다음으로 메인함수가 시작되고, getLength()함수로 guppy의 length값을 얻어왔습니다. 메인함수가 끝난 후, 객체가 소멸될 때에 소멸자가 호출될 것이고, 정의했던 것처럼 “소멸되었음!!!”이 출력되는 것을 확인할 수 있습니다.

이때 위의 코드에서 fish guppy(5) 인데 왜 length가 5로 지정되는 것일까요?

#include <iostream>
using std::cout;

class Dog {
  private:
    int age;
  public:
    Dog(int a) {age = a;}
    //생성자의 매개변수로 멤버 변수를 초기화하였습니다.
    int getAge() { return age; }
    void setAge(int a) { age = a; }
};


int main()
{
  Dog coco(3); // age = 3; 을 수행합니다.
  cout<<coco.getAge(); // 3이 나올 것입니다.

  cout<<"\n";

  coco.setAge(21); // age = 21; 을 수행합니다.
  cout<<coco.getAge(); // 21이 나올 것입니다.
  return 0;
}

//3
//21

생성자의 매개변수로 멤버 변수인 age를 초기화하였기 때문에 그렇습니다. 위의 코드의 결과가 왜 3과 21이 나오는지 이해하실 수 있을 것이라 생각합니다.

Thank you for visiting!

Thank you for visiting!

If you found this post helpful, please consider sharing and liking it. If you have any questions, feel free to leave a comment. 😎

If you’d like to contact me personally, please use the button below to send me an inquiry email. 📧