Notice
Recent Posts
Recent Comments
Link
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Archives
Today
Total
관리 메뉴

로또

16. new 및 delete를 사용할 때는 형태를 반드시 맞추자. 본문

책/Effective C++

16. new 및 delete를 사용할 때는 형태를 반드시 맞추자.

아롱로또 2023. 11. 13. 13:03

다루는 내용

new - delete, new[] - delete[]를 통해 할당되는 메모리 구조를 보고 형태를 맞추어야 하는 이유를 알자.

 

new, delete, 생성자, 소멸자

string* string_array = new string[100];
delete string_array;

위와 같은 코드는 문제없어 보이지만 미정의 동작을 보이기에 충분하다.

string_array가 가리키는 100개의 string 객체들 가운데, 99개는 정상적인 소멸 과정을 거치지 못하기 때문이다. 왜냐하면 소멸자가 충분한 횟수만큼 호출되지 못하기 때문이다.

class Test{
public:
    Test(){ cout << "Test Ctor" << endl; }
    ~Test(){ cout << "Test Dtor" << endl; }
};

위와 같은 클래스에 대해 다음과 같이 사용하면

int main(){
    Test* tests = new Test[4]; // 4개의 생성자
    delete tests; // 1개의 소멸자
}

4개의 생성자, 1개의 소멸자

이와 같은 실행 결과가 나타나며, 4개의 생성자가 호출된 것이 비해 소멸자는 1개만 호출된 모습을 볼 수 있다.

int main(){
    Test* tests = new Test[4]; // 4개의 생성자
    delete[] tests; // 4개의 소멸자
}

반대로, 올바르게 수정해주었을 때 결과이다.

4개의 생성자, 4개의 소멸자

 

우리가 new 연산자를 사용해서 어떤 객체를 동적 할당하면, 두 가지 내부 동작이 진행된다.

  1. operator new 를 통해 메모리가 할당된다.
  2. 할당된 메모리에 대해 한 개 이상의 생성자가 호출된다.

반대로, 우리가 delete 연산자를 사용하면 두 가지 내부 동작이 진행된다.

  1. 기존에 할당된 메모리에 대해 한 개 이상의 소멸자가 호출된다.
  2. operator delete를 통해 메모리가 해제된다.

이 때, delete 연산자가 적용되는 객체의 개수는 소멸자가 호출되는 횟수와 동일하다.

new로 생성된 하나의 객체와, new []로 생성된 객체 배열의 메모리 구조

메모리 구조 비교

배열을 위해 만들어지는 힙 메모리에는 대개 배열 원소의 개수가 함께 저장된다. 이 때문에, delete 연산자는 소멸자가 몇 번 호출되어야 하는지 알 수 있다.

반면, 단일 객체용 힙 메모리에는 그러한 정보가 없다.

즉, 어떤 포인터에 대해 delete를 적용할 때, delete 연산자로 하여금 "배열 크기 정보가 존재한다."는 것을 알려주기 위해서는 delete []를 사용해야 한다는 것이다. 그렇지 않으면 delete는 단일 객체라고 간주하고 1회의 소멸자만 호출될 것이다.

 

이것만은 잊지 말자!

  • new 표현식에 []를 썼으면, 대응되는 delete 표현식에도 []를 써야 합니다.
  • new 표현식에 []를 쓰지 않았으면, 대응되는 delete 표현식에도 []를 쓰지 말아야 합니다.