본문 바로가기
Object Oriented Programming(C++)/Effective C++

Effective C++ | 항목 16 new와 delete를 사용할 때는 형태를 반드시 맞추자

by continue96 2022. 1. 25.

항목 16 new와 delete를 사용할 때는 형태를 반드시 맞추자

16.1 객체와 객체 배열의 메모리 구조

 new 표현식을 사용해서 어떤 객체를 동적 할당하면 두 가지 내부 동작이 진행된다. 일단 operator new 함수가 사용되어 메모리가 할당된다. 그다음, 할당된 메모리에 대해 한 개 이상의 생성자가 호출된다. 반면, delete 표현식을 사용하면 또 다른 두 가지 내부 동작이 진행되는데, 우선 할당된 메모리에 대해 한 개 이상의 소멸자가 호출되고, 그 후에 operator delete 함수가 사용되어 메모리가 해제된다.

 new로 힙에 만들어진 객체의 메모리 배치 구조(layout)는 객체 배열의 메모리 배치 구조와 다르다. 특히, 배열을 위해 만들어지는 힙 메모리에는 대개 배열의 원소 개수, 즉 배열의 크기가 포함되는데, 이 때문에 delete 연산자는 소멸자가 몇 번 호출될지 알 수 있다. 반면, 객체를 위한 힙 메모리에는 이런 정보가 없다.

그림 16-1 객체와 객체 배열의 메모리 배치 구조

 

16.2 new에는 delete, new[]에는 delete[]

 여러분은 어떤 포인터에 대해 delete를 적용할 때 delete 연산자에게 배열의 크기 정보가 포함되어 있다는 것을 알려 줄 의무를 지고 있다. 이때 대괄호 쌍([])을 delete 뒤에 반드시 붙인다. 그제야 delete는 이 포인터가 객체를 가리키지 않고 객체 배열을 가리키고 있다고 간주한다.

std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[10];
...
delete stringPtr1; /* 객체를 삭제합니다. */
delete[] stringPtr2; /* 객체 배열을 삭제합니다. */

 어려울 것 하나 없다. new 표현식에 []를 썼으면 여기에 대응되는 delete 표현식에도 []를 쓴다. new 표현식에 []를 안 썼으면 대응되는 delete 표현식에도 []를 안 쓰면 된다.

 이 규칙은 typedef 애호가도 알아둘 가치가 있다. typedef로 정의된 어떤 타입의 객체 혹은 객체 배열을 메모리에 생성하려고 new를 썼을 때 어떤 delete를 적어야 하는지에 대한 책임을 typedef 타입 작성자가 져야 하는 의미로 볼 수 있다.

typedef std::string addressLines[5];
std::string* pal new addressLine; /* new addressLine은 new string[4]입니다. */
...
delete pal; /* 안 됩니다. 잘못된 삭제입니다. */
delete[] pal; /* 올바른 삭제입니다. */

 예를 들어, 어떤 typedef 타입이 다음과 같이 정의되어 있다고 가정해보자. addressLines는 보다시피 배열이므로 new를 사용하면 delete 역시 배열 형태([])가 되어야 한다.

 

NOTE
① new 표현식에 []를 썼으면 대응되는 delete 표현식에도 []를 써야 한다. 마찬가지로 new 표현식에 []를 안 썼으면 대응되는 delete 표현식에도 []를 쓰지 말아야 한다.

댓글