3 - 2학기/객체 지향 프로그래밍

객체지향 프로그래밍 : 생성자와 소멸자

harvartz의 일지 2021. 6. 13. 02:04

이번시간에는 생성자와 소멸자에 대해서 정리할 것이다. 생성자와 소멸자는 꽤나 중요하게 다루는 개념이기 때문에 꼭 기억하면서 넘어가자.

 

 

객체가 생성되고 소멸될 때, 자동으로 호출되는 것이 생성자와 소멸자이다. 

1. 객체의 메모리 할당

2. 생성자 호출

3. 객체 사용

4. 소멸자 호출

5. 객체의 메모리 해제 

 

위와 같은 순서로 객체가 생성되고 소멸된다.

 

특징

- 생성자와 소멸자는 객체가 생성, 소멸되는 시점에서 자동으로 호출되는 멤버함수이다.

- 생성자를 사용하는 이유는 객체에 필요한 초기화를 위해 사용하고 소멸자는 객체를 정리하기 위해 사용한다(메모리 해제와 같은)

- 생성자와 소멸자는 리턴 값이 없다.

 

- 생성자는 딱 한번만 호출한다.

- 생성자는 중복이 가능하다(오버로딩). 한 클래스에 여러개가 정의할 수 있지만 하나만 생성할 수 있다.

 

디폴트 생성자?

매개 변수가 없는 생성자를 말한다.

별도로 지정하지 않으면 항상 디폴트 생성자로 초기화가 된다.

 

* 생성자가 하나라도 선언되어 있는데 생성자에 맞지 않게 객체를 생성하면 컴파일 오류가 생긴다.

 

 

* const 멤버 변수, 레퍼런스 멤버 변수의 초기화

- 해당 멤버 변수는 변수를 만들고 대입하면 오류가 난다.

즉, 생성과 동시에 값을 대입해야 한다. 메모리 할당과 동시에 값이 있어야 한다.

 

그렇기 때문에 const 멤버 변수, 레퍼런스 멤버 변수는 초기화 리스트를 사용해야 한다.

이와 같은 경우는 오류가 난다.
초기화 리스트를 사용했을 때의 경우이다.


소멸자

: 객체가 소멸되는 시점에서 자동으로 호출되는 함수

 

- 오직 한번만 자동호출 한다.

- 객체 메모리 소멸 직전에 호출됨

- 인자를 가질 수 없어서 오버로딩을 할 수 없다.

- 리턴 타입이 없고, 리턴하면 안된다.

- 중복 불가능하다.

- 선언되어 있지 않으면 디폴트 소멸자 자동 생성

 

사용하는 목적

- 객체가 사라질 때 마무리 작업, 

- 실행 도중 동적으로 할당 받은 메모리 해제, 파일 저장 및 닫기, 네트워크 닫기

 

* 메인 함수가 종료되면 메인 함수의 스택에 생성된 객체가 소멸된다. 

* 객체는 생성의 반대순으로 소멸된다. 먼저 생성되면 나중에 소멸된다.

 


생성자, 소멸자 실행 순서(이 실행 순서로 문제가 나오지 않을까?)

 

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

- 지역 객체: 함수 내에 선언된 객체, 함수가 종료하면 소멸

- 전역 객체: 함수 바깥에 선언된 객체, 프로그램이 종료할 때 소멸

 

2. 객체 생성 순서

- 전역 객체는 프로그램에 선언된 순서로 생성

- 지역 객체는 함수가 호출되는 순간에 생성 (함수 안에서 객체를 생성하는 경우)

 

3. 객체 소멸 순서 

- 함수가 종료하면 지역객체가 생성된 순서로 역순으로 소멸

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

 

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

- new를 실행하는 순간 객체 생성

- delete 연산자를 실행할 때 객체 소멸

 


복사 생성자(이 부분 분명이 나옴, 헷갈렸다)

얕은 복사와 깊은 복사가 있다.

 

1. 얕은 복사

- 객체 복사 시, 객체의 멤벌르 1:1로 복사

- 객체의 멤버 변수에 동적 메모리 할당 경우

-> 사본은 원본 객체가 할당 받은 메모리를 공유하는 문제 발생

 

2. 깊은 복사

- 객체 복사 시, 객체의 멤버 1:1로 복사

- 객체의 멤버 변수에 동적 메모리가 할당된 경우

-> 사본은 원본이 가진 메모리 크기 만큼 별도로 동적할당

-> 원본의 동적 메모리에 있는 내용을 사본에 복사

즉, 완전한 형태의 복사이다. 사본과 원본은 메모리를 공유하는 문제가 생기지 않는다.

 

* 그렇다면 구현에 있어서 얕은 복사와 깊은 복사의 코드 차이는 무엇인가?

* 깊은 복사 생성자와 얕은 복사생성자의 차이를 확인해보자.

-> 깊은 복사 생성자의 경우 메모리가 공유될 수 있는 변수를 추가적으로 따로 메모리를 할당해줘야지 얕은 복사가 일어나지 않는다.

 

* 복사 생성자를 따로 정의하지 않으면 컴파일러가 디폴트 복사 생성자를 제공한다.