Programming Languages/C++

객체 생성과 수명 주기

newclass 2025. 3. 28. 00:00

5.4 객체 생성과 수명 주기

5.4.1 스택 객체 vs 힙 객체

C++에서 객체는 스택(자동 메모리)이나 힙(동적 메모리)에 생성될 수 있습니다:

#include <iostream>

class SimpleClass {
public:
    SimpleClass() {
        std::cout << "객체 생성됨" << std::endl;
    }
    
    ~SimpleClass() {
        std::cout << "객체 소멸됨" << std::endl;
    }
};

int main() {
    // 스택 객체 (자동 메모리)
    std::cout << "스택 객체 생성:" << std::endl;
    SimpleClass stackObj;  // 자동으로 생성/소멸
    
    // 힙 객체 (동적 메모리)
    std::cout << "힙 객체 생성:" << std::endl;
    SimpleClass* heapObj = new SimpleClass();  // 명시적으로 생성
    
    std::cout << "main 함수 마지막" << std::endl;
    
    delete heapObj;  // 명시적으로 소멸시켜야 함
    
    return 0;
}

출력 결과:

스택 객체 생성:
객체 생성됨
힙 객체 생성:
객체 생성됨
main 함수 마지막
객체 소멸됨
객체 소멸됨

스택 객체 vs 힙 객체:

  • 스택 객체: 블록이 끝나면 자동으로 소멸 (RAII 원칙)
  • 힙 객체: 명시적으로 delete해야 소멸 (메모리 누수 위험)

5.4.2 정적 멤버(Static Members)

정적 멤버는 클래스의 모든 객체가 공유하는 멤버입니다:

#include <iostream>
#include <string>

class Student {
private:
    std::string name;
    int id;
    static int totalStudents;  // 정적 데이터 멤버 선언
    
public:
    Student(const std::string& n) : name(n) {
        id = ++totalStudents;  // 새 학생이 생성될 때마다 증가
        std::cout << name << " 학생 등록 (ID: " << id << ")" << std::endl;
    }
    
    ~Student() {
        --totalStudents;
        std::cout << name << " 학생 제거" << std::endl;
    }
    
    // 정적 멤버 함수
    static int getTotalStudents() {
        return totalStudents;
    }
    
    void display() const {
        std::cout << "이름: " << name << ", ID: " << id << std::endl;
    }
};

// 정적 데이터 멤버 정의 및 초기화 (클래스 외부)
int Student::totalStudents = 0;

int main() {
    std::cout << "처음 학생 수: " << Student::getTotalStudents() << std::endl;
    
    // 객체 생성
    Student s1("홍길동");
    Student s2("김철수");
    
    std::cout << "현재 학생 수: " << Student::getTotalStudents() << std::endl;
    
    // 중괄호로 블록 생성
    {
        Student s3("이영희");
        std::cout << "블록 내 학생 수: " << Student::getTotalStudents() << std::endl;
    }  // s3 소멸
    
    std::cout << "블록 이후 학생 수: " << Student::getTotalStudents() << std::endl;
    
    return 0;
}

정적 멤버의 특징:

  • 클래스의 모든 객체가 공유
  • 객체 생성 전에도 존재 (className::staticMember로 접근)
  • 클래스 외부에서 정의 및 초기화 필요
  • 정적 멤버 함수는 정적 데이터 멤버만 접근 가능

5.4.3 상수 멤버 함수(Const Member Functions)

상수 멤버 함수는 객체의 상태를 변경하지 않는 함수로, 함수 선언 끝에 const 키워드를 붙여 정의합니다:

class Date {
private:
    int day, month, year;
    
public:
    Date(int d, int m, int y) : day(d), month(m), year(y) {}
    
    // 상수 멤버 함수 - 객체 상태 변경 불가
    void display() const {
        std::cout << day << "/" << month << "/" << year << std::endl;
        // day = 10;  // 오류: 상수 멤버 함수에서는 멤버 변수 수정 불가
    }
    
    // 비상수 멤버 함수 - 객체 상태 변경 가능
    void setDay(int d) {
        day = d;
    }
};

int main() {
    Date date(15, 8, 2023);
    date.display();  // 상수 멤버 함수 호출
    
    const Date constDate(25, 12, 2023);
    constDate.display();  // 상수 객체는 상수 멤버 함수만 호출 가능
    // constDate.setDay(26);  // 오류: 상수 객체는 비상수 멤버 함수 호출 불가
    
    return 0;
}

상수 멤버 함수의 장점:

  • 코드의 의도를 명확하게 전달
  • 상수 객체에서도 호출 가능
  • 컴파일러의 최적화 기회 제공
  • 프로그램의 안정성 향상