공부/C++

5. 생성자와 소멸자

bokob 2024. 4. 11. 21:17

5.1 생성자와 소멸자

객체의 생성 및 소멸

객체의 생성

객체가 생성될 때 생성자가 자동으로 호출된다.

 

객체의 소멸

객체가 소멸될 때 소멸자가 자동으로 호출된다.

생성자와 소멸자

생성자와 소멸자는 자동으로 호출되는 함수이다.

  • 생성자: 객체가 생성되는 시점에서 자동으로 호출되는 멤버 함수
  • 솜려자: 객체가 소멸되는 시점에서 자동으로 호출되는 멤버 함수

생성자와 소멸자 함수의 사용

  • 생성자: 객체가 생성될 때 객체가 필요한 초기화를 위해
  • 소멸자: 객체가 소멸될 때 객체의 정리를 위해

생성자와 소멸자 이름

  • 생성자: "클래스이름()" 형식의 함수    참고) 생성자는 매개변수 받을 수 있음
  • 소멸자:"~클래스이름()" 형식의 함수

생성자와 소멸자는 리턴 값이 없음

  • 리턴 타입 없음. void도 안됨

 

생성자 특징

객체 생성 시 오직 한 번만 호출

  • 자동으로 호출됨. 임의로 호출할 수 없음. 각 객체마다 생성자 실행

생성자는 중복 가능

  • 생성자는 한 클래스 내에 여러 개 가능
  • 중복된 생성자 중 하나만 실행

 

string 클래스의 생성자 중복 사례

class string{
    ...
public:
    string(); // 빈 문자열을 가진 스트링 객체 생성
    string(string& str); // str을 복사한 새로운 스트링 객체 생성
    string(char* s); // '\0'로 끝나는 C-스트링 s를 스트링 객체로 생성
    ...
};
string str; // 빈 문자열
string address("너네집");
string copyAddress(address); // address의 문자열을 복사한 별도의 copyAddress 생성

 

객체 생성 및 생성자 실행 과정

 

디폴트 생성자

1. 생성자는 꼭 있어야 하는가?

  • 있어야 한다. C++ 컴파일러는 객체가 생성될 때, 생성자 반드시 호출

2. 개발자가 클래스에 생성자를 작성해 놓지 않으면?

  • 컴파일러에 의해 기본 생성자가 자동으로 생성

디폴트 생성자란?

  • 매개변수 없는 생성자. 기본 생성자라고도 부름.
  • 객체를 생성할 때 별도로 지정하지 않으면 항상 디폴트 생성자로 초기화 됨
class Circle{
    ...
    Circle(); // 기본 생성자, 컴파일러가 자동 생성
};

 

디폴트 생성자가 자동으로 생성되는 경우

생성자가 하나도 작성되어 있지 않은 클래스의 경우

  • 컴파일러가 디폴트 생성자 자동 생성

 

디폴트 생성자가 자동으로 생성되지 않는 경우

생성자가 하나라도 선언된 클래스의 경우

  • 컴파일러는 디폴트 생성자를 자동 생성하지 않음

 

디폴트 인자를 사용한 함수 중복 간소화

디폴트 인자의 장점 - 함수 중복 간소화

 

중복 함수들과 디폴트 매개변수를 가진 함수를 함께 사용 불가

 

소멸자

소멸자 

  • 객체가 소멸되는 시점에서 자동으로 호출되는 함수
    • 오직 한번만 자동 호출, 임의로 호출할 수 없음
    • 객체 메모리 소멸 직전 호출됨
  • "~클래스이름()" 형식의 함수
  • 인자를 가질 수 없기 때문에 오버로딩할 수 없음

 

소멸자 특징

소멸자의 사용

  • 객체가 사라질 때 마무리 작업을 위함
  • 실행 도중 동적으로 할당 받은 메모리 해제, 파일 저장 및 닫기, 네트워크 닫기 등

소멸자는 리턴 타입이 없고, 어떤 값도 리턴하면 안됨

  • 리턴 타입 선언 불가

중복 불가능

  • 소멸자는 한 클래스 내에 오직 한 개만 작성 가능
  • 소멸자는 매개변수 없는 함수

소멸자가 선언되어 있지 않으면 디폴트(기본) 소멸자가 자동 생성

  • 컴파일러에 의해 디폴트 소멸자 코드 생성
  • 컴파일러가 생성한 디폴트 소멸자: 아무 것도 하지 않고 단순 리턴

 

Circle 클래스에 솜려자 작성 및 실행

 

생성자/소멸자 실행 순서

객체가 선언된 위치에 따른 분류

지역 객체

  • 함수 내에 선언된 객체로서, 함수가 종료하면 소멸된다.

전역 객체

  • 함수의 바깥에 선언된 객체로서, 프로그램이 종료할 때 소멸된다.

 

객체 생성 순서

  • 전역 객체는 프로그램에 선언된 순서로 생성
  • 지역 객체는 함수가 호출되는 순간에 순서대로 생성

 

객체 소멸 순서

  • 함수가 종료하면, 지역 객체가 생성된 순서의 역순으로 소멸
  • 프로그램이 종료하면, 전역 객체가 생성된 순서의 역순으로 소멸

 

new를 이용하여 동적으로 생성된 객체의 경우

  • new를 실행하는 순간 객체 생성
  • delete 연산자를 실행할 때 객체 소멸
int* a = new int;
delete a;

int* b = new int[10];
delete[] b;

기본적으로 생성 순서의 역순으로 소멸자가 호출되지만, delete로 해제하면 그때 바로 해제된다.

 

지역 객체와 전역 객체의 생성 및 소멸 순서

 

객체 간의 초기화와 대입

같은 클래스의 객체 간에 서로 초기화나 대입이 가능

객체 간의 초기화: 복사 생성자 이용

(본인 클래스와 같은 타입의 참조를 매개변수로 받음)

  • 같은 클래스의 다른 객체와 같은 값을 갖도록 초기화
  • 클래스의 멤버 변수를 1대1로 초기화

객체 간의 대입: 대입 연산자 이용

(컴파일러가 자동 생성해준다. 같은 타입은 메모리 구조가 같기 때문(단, 얕은 복사), 깊은 복사 하려면 연산자 오버로딩)

  • 같은 클래스의 다른 객체의 값을 대입
  • 클래스의 멤버 변수를 1대 1로 대입
Stack s1(5);
Stack s2 = s1;  // 객체 간의 초기화 = 복사 생성자
Stack s3;
s3 = s1;        // 객체 간의 대입, 대입 연산자

 

디폴트 함수들

개발자가 따로 정의하지 않으면 컴파일러에 의해서 제공되는 함수

  • 디폴트 생성자
  • 디폴트 소멸자
  • 디폴트 복사 생성자
  • 디폴트 대입 연산자

 

5.2 분할 컴파일

바람직한 C++ 프로그램 작성법

클래스를 헤더 파일과 cpp 파일로 분리하여 작성

  • 클래스마다 분리 저장
  • 클래스 선언 부: 헤더 파일(.h)에 저장
    • "클래스 이름.h"
  • 클래스 구현 부: cpp 파일에 저장(멤버함수의 구현)
    • 클래스가 선언된 헤더 파일 include
      • "클래스 이름.cpp"
  • main() 등 전역 함수나 변수는 다른 cpp 파일에 분산 저장
    • 필요하면 클래스가 선언된 헤더 파일 include

목적

  • 클래스 재사용

 

분할 컴파일

명령어)

g++ -o main.cpp Circle.cpp

./main.exe

 

헤더 파일의 중복 include 문제

헤더 파일을 중복 include 할 때 생기는 문제

결과적으로 이렇게 되는데 아래 예시처럼 된다는 것이다.

 

헤더 파일의 중복 include 문제를 조건 컴파일로 해결

헤더의 중복 포함을 막는 방법

  • 규칙1. 헤더 파일의 이름을 따서 심볼을 만든다 (예: TEST_H)  
  • 규칙2. 헤더 파일의 제일 앞에 이 심볼을 사용해서 #ifndef, #define 명령을 추가한다.
  • 규칙3. 헤더 파일의 제일 끝에 #endif를 추가한다.
  • 참고) #pragma once 도 있지만 지원 안하는 컴파일러도 있음

'CIRCLE_H를 define 하지 않았다면, #endif 가 나오기 전까지를 포함시켜라.' 라는 것이다.

 

'공부 > C++' 카테고리의 다른 글

7. 여러가지 객체의 생성방법  (0) 2024.05.14
6. 접근지정자, const 객체, static 멤버  (1) 2024.04.18
4. 클래스와 객체의 기본  (0) 2024.04.09
3. 개선된 함수 기능  (0) 2024.03.31
2. 포인터와 레퍼런스  (1) 2024.03.30