C++ 프로그래밍

C++의 생성자와 소멸자: 객체의 생명주기 관리

ROBL 2025. 2. 8.
728x90
반응형

C++에서 생성자와 소멸자는 객체의 생명주기를 관리하는 중요한 구성 요소입니다. 생성자는 객체가 생성될 때 자동으로 호출되어 초기화를 담당하며, 소멸자는 객체가 소멸될 때 호출되어 자원을 해제하는 역할을 합니다. 이 글에서는 생성자와 소멸자의 개념, 종류, 사용법, 그리고 주의사항에 대해 자세히 살펴보겠습니다.

1. 생성자란?

생성자는 클래스의 인스턴스(객체)가 생성될 때 자동으로 호출되는 특별한 메서드입니다. 생성자는 객체의 초기화를 담당하며, 클래스와 동일한 이름을 가지며 반환 타입이 없습니다.

1.1 생성자의 기본 구조

생성자는 다음과 같은 기본 구조를 가집니다.

class ClassName {
public:
    // 생성자
    ClassName() {
        // 초기화 코드
    }
};

위의 코드에서 ClassName은 클래스의 이름이며, 생성자는 해당 클래스의 객체가 생성될 때 호출됩니다.

1.2 생성자의 예제

다음은 생성자를 사용하는 간단한 예제입니다.

#include <iostream>
using namespace std;

class Person {
public:
    string name;
    int age;

    // 생성자
    Person(string n, int a) {
        name = n;
        age = a;
    }

    void introduce() {
        cout << "안녕하세요, 제 이름은 " << name << "이고, 나이는 " << age << "세입니다." << endl;
    }
};

int main() {
    Person person("Alice", 30); // 생성자 호출
    person.introduce(); // 메서드 호출
    return 0;
}

위의 코드에서 Person 클래스의 생성자는 이름과 나이를 매개변수로 받아 객체를 초기화합니다. main 함수에서 Person 객체를 생성할 때 생성자가 호출되어 초기값이 설정됩니다.

2. 소멸자란?

소멸자는 클래스의 인스턴스가 소멸될 때 자동으로 호출되는 특별한 메서드입니다. 소멸자는 자원 해제를 담당하며, 클래스 이름 앞에 ~ 기호를 붙여 정의합니다.

2.1 소멸자의 기본 구조

소멸자는 다음과 같은 기본 구조를 가집니다.

class ClassName {
public:
    // 소멸자
    ~ClassName() {
        // 자원 해제 코드
    }
};

위의 코드에서 ClassName의 소멸자는 해당 클래스의 객체가 소멸될 때 호출됩니다.

2.2 소멸자의 예제

다음은 소멸자를 사용하는 간단한 예제입니다.

#include <iostream>
using namespace std;

class Person {
public:
    string name;
    int age;

    // 생성자
    Person(string n, int a) {
        name = n;
        age = a;
    }

    // 소멸자
    ~Person() {
        cout << name << "의 객체가 소멸되었습니다." << endl;
    }

    void introduce() {
        cout << "안녕하세요, 제 이름은 " << name << "이고, 나이는 " << age << "세입니다." << endl;
    }
};

int main() {
    Person person("Alice", 30); // 생성자 호출
    person.introduce(); // 메서드 호출
    return 0; // main 함수 종료 시 소멸자 호출
}

위의 코드에서 Person 클래스의 소멸자는 객체가 소멸될 때 해당 객체의 이름을 출력합니다. main 함수가 종료되면 person 객체가 소멸되고, 소멸자가 호출됩니다.

3. 생성자의 종류

C++에서는 여러 종류의 생성자를 정의할 수 있습니다.

3.1 기본 생성자

기본 생성자는 매개변수가 없는 생성자로, 객체를 기본값으로 초기화합니다.

class Person {
public:
    string name;
    int age;

    // 기본 생성자
    Person() {
        name = "Unknown";
        age = 0;
    }
};

3.2 매개변수 생성자

매개변수 생성자는 매개변수를 받아 객체를 초기화합니다. 위의 예제에서 이미 설명했습니다.

3.3 복사 생성자

복사 생성자는 다른 객체를 기반으로 새로운 객체를 생성할 때 사용됩니다. 복사 생성자는 다음과 같이 정의됩니다.

class Person {
public:
    string name;
    int age;

    // 복사 생성자
    Person(const Person &p) {
        name = p.name;
        age = p.age;
    }
};

복사 생성자는 객체를 복사할 때 호출되며, 기존 객체의 속성을 새로운 객체에 복사합니다.

4. 소멸자의 중요성

소멸자는 자원 해제를 담당하므로, 메모리 누수와 같은 문제를 방지하는 데 중요한 역할을 합니다. 동적 메모리를 할당한 경우, 소멸자에서 해당 메모리를 해제해야 합니다.

class Person {
public:
    string name;
    int* age; // 동적 메모리 할당

    // 생성자
    Person(string n, int a) {
        name = n;
        age = new int(a); // 동적 메모리 할당
    }

    // 소멸자
    ~Person() {
        delete age; // 동적 메모리 해제
        cout << name << "의 객체가 소멸되었습니다." << endl;
    }
};

위의 코드에서 age는 동적 메모리로 할당되며, 소멸자에서 delete를 사용하여 메모리를 해제합니다.

5. 주의사항

  • 생성자와 소멸자의 일관성: 생성자에서 동적 메모리를 할당한 경우, 반드시 소멸자에서 해당 메모리를 해제해야 합니다. 그렇지 않으면 메모리 누수가 발생할 수 있습니다.
  • 복사 생성자와 대입 연산자: 복사 생성자와 대입 연산자를 정의할 때는 깊은 복사(deep copy)와 얕은 복사(shallow copy)의 개념을 이해해야 합니다. 기본적으로 C++는 얕은 복사를 수행하므로, 동적 메모리를 사용하는 경우 깊은 복사를 구현해야 합니다.
  • 가상 소멸자: 상속을 사용하는 경우, 부모 클래스의 소멸자를 가상으로 선언하는 것이 좋습니다. 이를 통해 자식 클래스의 소멸자가 올바르게 호출되도록 보장할 수 있습니다.
class Base {
public:
    virtual ~Base() { // 가상 소멸자
        // 자원 해제 코드
    }
};

class Derived : public Base {
public:
    ~Derived() {
        // 자원 해제 코드
    }
};

6. 결론

C++의 생성자와 소멸자는 객체의 생명주기를 관리하는 핵심 요소입니다. 생성자는 객체의 초기화를 담당하며, 소멸자는 자원 해제를 통해 메모리 누수를 방지합니다. 다양한 종류의 생성자와 소멸자를 이해하고 적절히 활용함으로써, 리소스를 올바르게 사용하는 안정적인 C++ 프로그램을 작성할 수 있습니다. 다음 포스팅에서는 C++의 메서드에 대해 더 깊이 다루어 보겠습니다.

728x90
반응형

댓글

💲 추천 글