소멸자 심층 탐구
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 24번째.
소멸자(destructor)는 객체가 소멸될 때 자동으로 실행되는 특별한 멤버 함수입니다. 소멸자의 주요 역할은 동적으로 할당된 메모리, 파일 핸들 또는 네트워크 연결과 같이 객체가 수명 주기 동안 획득한 리소스를 해제하는 것입니다.
소멸자는 클래스와 동일한 이름을 가지며, 앞에 물결표 ~가 붙습니다. 소멸자는 매개변수를 받지 않으며 반환 타입이 없습니다:
class FileHandler {
std::string filename;
int* buffer;
public:
FileHandler(std::string name, size_t size)
: filename(name), buffer(new int[size]) {
std::cout << "Opening " << filename << "\n";
}
~FileHandler() {
delete[] buffer;
std::cout << "Closing " << filename << "\n";
}
};소멸자는 다음과 같은 상황에서 자동으로 호출됩니다:
- 스택 객체가 범위를 벗어날 때
- 힙에 할당된 객체에 대해
delete가 호출될 때 - 임시 객체의 수명이 끝날 때
void example() {
FileHandler f1("data.txt", 100); // 생성자 호출됨
FileHandler* f2 = new FileHandler("log.txt", 50);
delete f2; // f2에 대해 소멸자 호출됨
} // f1에 대해 소멸자 호출됨 (범위를 벗어남)생성자와 달리, 클래스는 단 하나의 소멸자(destructor)만을 가질 수 있습니다. 이를 오버로드(overload)할 수 없습니다.
만약 정의하지 않으면, 컴파일러는 특별한 작업을 수행하지 않고 단순히 각 멤버를 파괴하는 기본 소멸자를 생성합니다. 리소스를 관리하는 클래스의 경우, 메모리 누수를 방지하기 위해 직접 소멸자를 작성해야 합니다.
챌린지
쉬움활성 사용자 세션을 추적하고, 객체가 소멸될 때(범위를 벗어나거나 명시적으로 삭제될 때) 소멸자가 어떻게 자동으로 리소스를 정리하는지 보여주는 세션 관리자를 만들어 보겠습니다.
코드를 구성하기 위해 두 개의 파일을 생성합니다:
Session.h: 동적으로 할당된 데이터를 사용하여 활성 사용자 세션을 나타내는Session클래스를 정의합니다. 클래스에는 다음이 포함되어야 합니다:- 프라이빗 멤버:
username(string),sessionId(int), 사용자 작업을 추적하는activityLog라는 정수 배열 포인터, 그리고 배열 크기를 위한logSize - 사용자 이름, 세션 ID, 로그 크기를 매개변수로 받는 생성자. 힙에 활동 로그 배열을 할당하고, 모든 요소를 0으로 초기화하며,
"Session <sessionId> started for <username>"를 출력해야 합니다. - 할당된 메모리를 해제하고
"Session <sessionId> ended for <username>"를 출력하는 소멸자 - 활동 코드를 다음 사용 가능한 슬롯에 저장하는
logActivity(int activityCode)메서드 (내부적으로 현재 위치를 추적함) - 기록된 활동 수를 반환하는
getActivityCount()메서드 - 사용자 이름을 반환하는
getUsername()메서드
- 프라이빗 멤버:
main.cpp: 다양한 시나리오에서 소멸자의 동작을 보여줍니다. 입력에서 사용자 이름과 로그 크기를 읽은 후(각각 별도의 줄에 있음), 다음을 수행합니다:- 중괄호
{ }를 사용하여 스코프 블록을 만들고, 그 안에 입력받은 사용자 이름, 세션 ID101, 입력받은 로그 크기로 스택 할당Session을 생성합니다. 코드1과2로 두 개의 활동을 기록한 다음,"Stack session activities: <count>"를 출력합니다. 블록이 끝나면 소멸자가 자동으로 실행되어야 합니다. - 블록이 끝난 후,
"Stack session destroyed"를 출력합니다. new를 사용하여 사용자 이름"Guest", 세션 ID202, 로그 크기3으로 힙 할당Session을 생성합니다. 코드5로 하나의 활동을 기록하고,"Heap session activities: <count>"를 출력한 다음, 명시적으로delete합니다.- 삭제 후,
"Heap session destroyed"를 출력합니다.
- 중괄호
이 챌린지는 소멸자가 호출되는 두 가지 주요 방식인 스택 객체가 범위를 벗어날 때 자동으로 호출되는 방식과 힙 객체를 삭제할 때 수동으로 호출되는 방식을 보여줍니다. 두 경로 모두 메모리 누수를 방지하기 위해 동적으로 할당된 활동 로그를 적절히 해제해야 합니다.
#include "Session.h"를 사용하여 main.cpp에 헤더 파일을 포함하세요.
치트 시트
소멸자는 객체가 파괴될 때 자동으로 실행되는 특별한 멤버 함수입니다. 동적으로 할당된 메모리, 파일 핸들 또는 네트워크 연결과 같은 리소스를 해제하는 역할을 합니다.
소멸자는 클래스와 이름이 같으며, 앞에 물결표 ~가 붙습니다. 매개변수를 받지 않으며 반환 타입도 없습니다:
class FileHandler {
std::string filename;
int* buffer;
public:
FileHandler(std::string name, size_t size)
: filename(name), buffer(new int[size]) {
std::cout << "Opening " << filename << "\n";
}
~FileHandler() {
delete[] buffer;
std::cout << "Closing " << filename << "\n";
}
};소멸자는 다음과 같은 경우에 자동으로 호출됩니다:
- 스택 객체가 범위를 벗어날 때
- 힙에 할당된 객체에 대해
delete가 호출될 때 - 임시 객체의 수명이 끝날 때
void example() {
FileHandler f1("data.txt", 100); // 생성자 호출됨
FileHandler* f2 = new FileHandler("log.txt", 50);
delete f2; // f2에 대한 소멸자 호출됨
} // f1에 대한 소멸자 호출됨 (범위를 벗어남)클래스는 오직 하나의 소멸자만 가질 수 있습니다 (오버로딩 불가). 소멸자를 직접 정의하지 않으면 컴파일러가 기본 소멸자를 생성합니다. 리소스를 관리하는 클래스의 경우, 메모리 누수를 방지하기 위해 직접 소멸자를 작성해야 합니다.
직접 해보기
#include <iostream>
#include <string>
#include "Session.h"
using namespace std;
int main() {
// 입력 읽기
string username;
int logSize;
getline(cin, username);
cin >> logSize;
// TODO: 중괄호 { }를 사용하여 스코프 블록 생성
// 블록 내부:
// - 입력받은 username, 세션 ID 101, 입력받은 logSize를 사용하여 스택 할당 Session 생성
// - 코드 1과 2로 두 개의 활동 로그 기록
// - "Stack session activities: <count>" 출력
// 블록이 끝나면 소멸자가 자동으로 실행됨
// TODO: 블록이 끝난 후, "Stack session destroyed" 출력
// TODO: new를 사용하여 힙 할당 Session 생성
// - Username: "Guest", 세션 ID: 202, 로그 크기: 3
// - 코드 5로 하나의 활동 로그 기록
// - "Heap session activities: <count>" 출력
// - 세션 삭제(delete)
// TODO: 삭제 후, "Heap session destroyed" 출력
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.