관리 메뉴

Kim's Programming

C++ - 파괴자(Destructor) 본문

Programming/Cplusplus

C++ - 파괴자(Destructor)

Programmer. 2015. 8. 30. 14:59

파괴자(Destructor)


생성자는 주로 멤버 변수의 값을 원하는 값으로 대입하는 작업을 하지만 그 외 객체가 동작하는데 필요한 모든 초기화 처리를 담당하기도 합니다. 앞의 코드를 보면서 가겠습니다.

1
2
3
4
5
6
7
8
class RandNum
{
public:
    RandNum()
    {
        srand(time(NULL));
    }
};
cs

RandNum객체는 난수를 캡슐화 하는데 난수가 무작위로 생성되려면 srand(time(NULL)) 함수로 난수 발생기를 초기화해야합니다. 이 작업을 생성자가 담당함으로써 객체를 생성하는 즉시 난수 발생기가 초기화됩니다. 이외에 필요한 버퍼를 동적으로 할당하거나 객체가 사용하는 파일을 오픈하는 일도 생성자의 몫입니다. 요컨데 생성자가 객체가 제대로 동작하기 위한 모든 처리를 담당하는 함수입니다. 생성자가 객체 자체의 초기화외에 외부 환경까지 초기화하기 떄문에 객체가 사라질 때 반대의 처리를 할 함수도 필요합니다. 객체나 메모리 또는 프로그램등 컴퓨터 안에서 움직이는 모든 것들은 항상 자신이 생성되기 전의 상태로 환경을 돌려놓을 의무가 있습니다. 객체가 통신을 위해 네트워크 연결을 했다면 자신이 사라질 때 이 연결을 끊어야 하며 할당된 메모리를 해제해야 합니다.


이러한 뒷처리를 하는 특별한 멤버 함수를 파괴자(Destructor)라고 하며 객체가 소멸될 때 컴파일러에 의해 자동으로 호출됩니다. 파괴자의 이름은 클래스 이름 앞에~(tidle라고 읽습니다)을 붙인 것으로 고정되어 있으며 인수와 리턴값은 가지지 않습니다. 다음 소스는 파괴자에 대한 예시소스입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string.h>
using namespace std;
class Person
{
private:
    char *Name;
    int Age;
 
public:
    Person(const char *aName, int aAge)
    {
        Name = new char[strlen(aName) + 1];
        strcpy(Name, aName);
        Age = aAge;
    }
    ~Person()
    {
        delete[] Name;
    }
    void OutPerson()
    {
        cout << "이름 : " << Name << "나이 : " << Age << endl;
    }
};
void main()
{
    Person Per("홍길동"23);
    Per.OutPerson();
}
cs

Person 클래스는 사람을 표현하는데 이름과 나이를 멤버 변수로 가집니다. 나이는 정수값이므로 int형 이면 충분하지만 외국인 이나 더 긴 이름을 좋아하는 사람인 경우는 그 이상을 하는 경우도 있습니다. 그래서 고정된 길이의 버퍼를 사용하는 것은 위험하며 입력된 이름의 길이만큼 버퍼를 동적으로 할당해야합니다. 생성자는 인수로 전달된 이름의 길이만큼 Name버퍼를 동적으로 할당하여 이 버퍼에 이름을 저장하는데 이런식이면 긴 이름도 얼마든지 표현이 가능합니다. 생성자에서 별도의 버퍼를 직접 할당 하였기 떄문에 Name이 가리키는 버퍼는 객체 내부에 있지 않고 외부의 힙에 따로 존재합니다. 객체는 Name멤버를 통해 이름이 저장되어있는 메모리 주소를 가리키고 있을 뿐입니다.


이상태에서 객체가 파괴되면 객체가 점유하고 있는 모든 메모리는 자동으로 해체욉니다. Per 객체는 main함수의 지역변수이므로 main이 종료될 때 파괴되는데 이때 Name 멤버와 Age 멤버가 차지하고 있는 8바이트가 해제될 것입니다. Name멤버 자체는 해제되지만 Name이 가리키고 있는 힙의 메모리는 동적으로 할당 된 것이므로 자동으로 해제되지 않습니다. 그래서 객체가 파괴될 때 반드시 직접 해제해야하며 이런 처리를 하는 함수가 파괴자입니다. 예제의 ~Person 파괴자는 Name 멤버가 차지하고 있는 메모리를 해제합니다. Name이 new로 할당되었기 떄문에 delete로 해제를 해줍니다.


파괴자는 객체가 사라질 때 컴파일러에 의해 자동으로 호출되는데 객체가 바꿔 놓은 환경을 원래대로 돌려놓거나 할당한 자원을 회수하는 역할을 합니다. 앞에 있던 Position 클래스는 파괴될 때 특별히 할 일이 없으므로 파괴자가 불 필요하지만 이 Person클래스는 생성자에서 메모리를 동적으로 할당하므로 이 메모리를 해제할 파괴자가 반드시 필요하게 됩니다. 만약 파괴자가 정의되어있지 않다면 할당된 메모리는 계속 누적되어 메모리 누수가 발생할 것입니다.

'Programming > Cplusplus' 카테고리의 다른 글

C++ - 클래스 생성자/파괴자(2/3)  (2) 2015.08.31
C++ - 클래스 생성자/파괴자(1/3)  (1) 2015.08.30
C++ - 생성자(Constructor)  (0) 2015.08.29
C++ - 클래스(Class)(2/2)  (0) 2015.08.28
C++ - 클래스(Class)(1/2)  (0) 2015.08.28