프로그래밍/C++

[C++] 소멸자 (destructor)

갓똥 2019. 11. 4. 23:31
728x90
반응형

1. 소멸자 개념

#include <iostream>

class Point {
    int x, y;
public:
    Point()  { std::cout << "Point()"  << std::endl; }  // 생성자
    ~Point() { std::cout << "~Point()" << std::endl; }  // 소멸자
};

int main() {
    Point pt;
}

  ① 소멸자 모양

    => ~클래스이름()

    => 리턴 타입을 표기하지 않는다.

    => 인자를 가질 수 없다. - 한 개만 만들 수 있다.

 

  ② 특징

    => 객체를 생성 하면 생성자가 호출되고

    => 객체가 파괴 되면 소멸자가 호출된다.

 

  ③ 소멸자를 만들지 않으면

    => 컴파일러가 아무 일도 하지 않는 소멸자를 제공해 준다.

 

  ④ 소멸자가 필요한 경우

    => 생성자 등에서 자원을 할당한 경우, 소멸자에서 자원을 해지 해야 한다.

    => 자원 해지 등이 필요 없는 경우는 소멸자를 만들 필요는 없다.

 


2. 소멸자 사용 예제

#include <stdio.h>

int main() {
    FILE* f = fopen("a.txt", "wt");
    
    // f = 0; - 변수에 접근할 수 있어 실수할 수 있다.
    
    fputs("hello", f);
    
    fclose(f);
}

 

위와 같은 C언어로 짠 코드가 있다고 해보자.
위의 코드의 단점은 사용자가 쓸 파일을 열고 꼭 닫아주어야 한다는 것이다.
또, 파일의 정보를 들고 있는 f에 접근이 가능하여 실수할 경우 f가 날라갈 수도 있다.

  ① C 스타일 코드의 단점

    => 획득한 자원은 반드시 사용자가 직접 반납해야 한다.

    => 자원의 핸들을 담은 변수에 직접 접근 할 수 있다.

 

  ② 자원 할당과 자원 해지가 필요한 코드

    => C++을 사용해서 생성자에서 자원을 할당하고 소멸자에서 자원을 해지하면 자동으로 자원이 관리된다.

    => RAII (Resource Acquision Is Initialization)

 

#include <iostream>
#include <cstdio>
#include <string>

int main() {
    FILE* f = fopen("a.txt", "wt");
    
    f = 0; // 변수에 실수로 값을 넣었을 때
    
    fputs("hello", f);
    
    fclose(f);
}

 

위의 코드를 C++로 바꾼 코드이다. 이제 Class를 이용해서 C 스타일 코드의 단점을 없애보자.

 

#include <iostream>
#include <cstdio>
#include <string>

class File {
    FILE* file = 0; // C++11부터 바로 초기화 가능
public:
    File(std::string filename, std::string mode) {
        file = fopen(filename.c_str(), mode.c_str()); 
    }
    ~File() {
        fclose(file);
    }
    void puts(std::string s) {
        fputs(s.c_str(), file);
    }
};

int main() {
    File f("a.txt", "wt");
    
    f.puts("hello");
    
    /*
    FILE* f = fopen("a.txt", "wt");
    f = 0; - 접근 불가
    fputs("hello", f);
    fclose(f);
    */
}

  ① C++에서 가장 널리 사용되는 코딩 스타일

    => 생성자에서 자원을 할당한다.

    => 소멸자에서 자원을 반납한다.

    => 자원의 번호를 담은 멤버 변수는 private 영역에 놓고 외부에서 직접 접근할 수 없게 한다

728x90
반응형