[C++] 항목 16: new 및 delete를 사용할 때는 형태를 반드시 맞추자
카테고리: Cpp
태그: Cpp
이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
이펙티브 C++ 제3판, 스콧 마이어스 저자, 곽용재 번역
📦 3. 자원 관리
👉🏻 항목 16: new 및 delete를 사용할 때는 형태를 반드시 맞추자
동적 할당 시 new
를 사용하고, 해제할 때는 delete
를 사용한다.
하지만 배열을 할당했다면 delete[]
로 해제해야 한다.
string *stringArray = new string[100];
...
delete stringArray; // ❌ 잘못된 코드
위 코드는 new[]
로 배열을 할당했음에도 불구하고, delete
로 단일 객체 삭제를 시도하고 있다.
이런 경우, 첫 번째 객체만 소멸되고, 나머지 객체들의 소멸자는 호출되지 않아서
정의되지 않은 동작이 발생할 수 있다.
✅ 배열의 메모리 구조는 단일 객체와 다르다
배열을 할당하면, 런타임에서 배열의 크기 정보도 함께 저장된다.
이 정보는 delete[]
가 호출될 때 각 원소의 소멸자를 정확히 호출하기 위해 필요하다.
-
배열 구조 예시:
| 배열 크기 n | 객체 1 | 객체 2 | … | | ——- | —- | —- | — |
-
단일 객체 구조 예시:
| 객체 1 | | —- |
따라서 delete
와 delete[]
는 내부 동작이 완전히 다르며, 서로 교차해서 사용하면 안 된다.
✅ new와 delete는 반드시 형태를 맞춰야 한다
string *stringPtr1 = new string;
string *stringPtr2 = new string[100];
delete stringPtr1; // ✅ 단일 객체 삭제
delete [] stringPtr2; // ✅ 배열 삭제
new
에[]
를 사용했다면,delete
에도 반드시[]
를 붙여야 한다.new
에[]
를 사용하지 않았다면,delete[]
도 사용해서는 안 된다.
→ 짝을 정확히 맞추지 않으면 정의되지 않은 동작이 발생할 수 있다.
⚠️ typedef로 인해 배열이라는 사실이 감춰질 수 있다
// AddressLines == string[4]
typedef string AddressLines[4];
// string *pal = new string[4];
string *pal = new AddressLines;
delete pal; // ❌ 단일 객체 삭제
delete [] pal; // ✅ 배열 삭제
typedef
를 통해 배열 타입을 감추면, 포인터가 배열을 가리킨다는 사실을 놓치기 쉽다.
이로 인해 delete
와 delete[]
를 혼동할 위험이 커진다.
→ 배열 타입을 typedef로 감추는 것은 피하는 것이 좋다.
✅ 안전한 대안: vector 사용
std::vector
나 std::array
와 같은 컨테이너를 사용하면 이러한 실수를 방지할 수 있다.
vector<string> pal(4);
- 메모리 해제는 자동으로 이루어지고
- 생성자/소멸자 호출도 자동
- 타입도 명확하게 드러나서 실수할 일이 없다
→ 직관적이고 안전한 대안이다.
🧐 정리
new[]
로 할당한 메모리는 반드시delete[]
로 해제해야 한다new
와delete
는 형태를 정확히 맞춰 써야 한다 (단일 vs 배열)- 배열 타입을
typedef
로 감추면 실수하기 쉬우므로 지양하자 - 가능하면
vector
나array
같은 컨테이너를 사용하는 것이 가장 안전하다
댓글남기기