728x90
황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!
https://search.shopping.naver.com/book/catalog/32436115747
소멸자
- 객체가 소멸되면 객체 메모리는 시스템으로 반환
- 소멸자(destructor)는 객체가 소멸되는 시점에서 자동으로 호출되는 클래스의 멤버 함수
class Circle{
Circle();
Circle(int r);
// .....
~Circle();
};
Circle::~Circle() {
.....
}
특징
- 소멸자의 목적은 객체가 사라질 때 필요한 마무리 작업을 위함이다.
- 동적으로 할방받은 메모리를 운영체제에게 돌려주거나,
- 열어 놓은 파일을 저장하고 닫거나
- 연결된 네트워크를 해제하는 등의 작업을 하기 위함
- 소멸자의 이름은 클래스 이름 앞에 ~를 붙인다.
- Circle 클래스의 소멸자 이름은 ~Circle()이며, 소멸자는 다음과 같이 작성
- Circle::~Circle() { ... }
- 소멸자는 리턴 타입이 없으며 어떤 값도 리턴해서도 안 된다.
- 소멸자는 생성자와 같이 리턴 타입 없이 선언되며 어떤 값도 리턴해서는 안됨
- 소멸자는 오직 한 개만 존재하며 매개 변수를 가지지 않음
- 생성자와 달리 한 클래스에 한 개만 존재하며 매개 변수를 가지지 않는다.
- 소멸자가 선언되어 있지 않으면 기본 소멸자(default destructor)가 자동으로 생성
- 생성자와 마찬가지로 소멸자가 없는 클래스는 컴파일러에 의해 자동으로 기본 소멸자가 주어지며, 이 때 기본 소멸자는 단순 리턴만 함
실행
- 클래스에 소멸자를 추가하고, 소멸자가 실행되면 메시지를 출력하도록 해보자.
#include <iostream>
using namespace std;
class Circle {
public:
int radius;
Circle();
Circle(int r);
~Circle(); // 소멸자
double getArea();
};
Circle::Circle() {
radius = 1;
cout << "반지름 " << radius << " 원 생성" << endl;
}
Circle::Circle(int r) {
radius = r;
cout << "반지름 " << radius << " 원 생성" << endl;
}
Circle::~Circle() {
cout << "반지름 " << radius << " 원 소멸" << endl;
}
double Circle::getArea() {
return 3.14*radius*radius;
}
int main() {
Circle donu;
Circle pizza(30);
return 0;
}
/*
반지름 1 원 생성
반지름 30 원 생성
반지름 30 원 소멸
반지름 1 원 소멸
*/
- main()의 스택에 donu, pizza의 순서로 객체 생성 후 return 0문이 실행
- 생성 반대 순으로 pizza, donu 객체가 소멸
생성자/ 소멸자 실행 순서
- 함수 내에서 선언된 객체 => 지역 객체(local object)
- 함수 바깥에 선언된 객체 => 전역 객체(global object)
지역 객체 : 함수가 실행될 때 생성, 종료할 때 소멸
전역 객체 : 프로그램 로딩시 생성, main()이 종료한 뒤 프로그램 메모리가 사라질 때 소멸
둘다 생성된 순서의 반대순으로 소멸된다.
#include <iostream>
using namespace std;
class Circle {
public:
int radius;
Circle();
Circle(int r);
~Circle();
double getArea();
};
Circle::Circle() {
radius = 1;
cout << "반지름 " << radius << " 원 생성" << endl;
}
Circle::Circle(int r) {
radius = r;
cout << "반지름 " << radius << " 원 생성" << endl;
}
Circle::~Circle() {
cout << "반지름 " << radius << " 원 소멸" << endl;
}
double Circle::getArea() {
return 3.14*radius*radius;
}
Circle globalDonut(1000);
Circle globalPizza(2000);
void f() {
Circle fDonut(100);
Circle fPizza(200);
}
int main() {
Circle mainDonut;
Circle mainPizza(30);
f();
}
힙 객체
- 위와 반대로 힙 객체는 자동으로 삭제되지 않는다 => 스마트 포인터를 사용하지 않은 경우!!
- 따라서, 객체 포인터에 대해 delete를 명시적으로 호출하고 메모리를 해제 해야 한다.
- 기본 생성자의 경우 stack에 생성됨
// 명시적 소멸자 호출 예제
int main() {
Person* pPtr1 = new Person("jin", 27);
Person* pPtr2 = new Person("chul", 26);
cout << "jin의 나이: " << pPtr1->getAge() << endl;
delete pPtr1; // pPtr1이 가리키는 메모리 공간(힙)을 해제한다.
pPtr1 = nullptr; // 잘못된 잘못을 막고자 널을 대입
return 0;
}
// pPtr2에 대해선 delete를 통해 가리키는 메모리 공간을 해제하지 않았다.
- 위와 같이 포인터가 가리키는 공간을 해제하지 않고 남겨두면 안 된다.
- 항상 delete or delete[]를 호출해서 동적으로 할당된 메모리를 해제해야 한다.
- 이러한 실수를 막기 위해서는 스마트 포인터를 사용하는 방법이 있다.
728x90
'Programming Language > C++' 카테고리의 다른 글
[C++] priority queue with Cpp (0) | 2023.11.29 |
---|---|
[C++] 접근 지정자와 인라인 함수 (0) | 2023.11.29 |
[C++] 생성자 (1) | 2023.11.27 |
[C++] 클래스와 객체 (1) | 2023.11.27 |
[C++] 키보드로 문자열 입력 및 헤더 파일에 관해서 (1) | 2023.11.27 |