WIPIVERSE

new와 delete (C++)

개념 개요
new와 delete는 C++ 표준에 정의된 연산자로, 동적 메모리 할당과 해제를 담당한다. new는 힙 영역(heap)에서 객체나 배열을 생성하고, 해당 객체의 주소를 반환한다. delete는 new에 의해 할당된 메모리를 반환하고, 객체의 소멸자를 호출한다.

주요 특징

특징 new delete
동작 힙 영역에서 지정된 타입 또는 타입 배열을 할당 new로 할당된 메모리를 해제
반환값 할당된 객체(또는 배열)의 포인터 반환값 없음
예외 할당 실패 시 std::bad_alloc 예외 발생 (예외를 비활성화한 경우 nullptr 반환) 해제 중 오류가 발생하면 정의되지 않은 동작(UB)
소멸자 호출 할당 시 자동 호출되지 않음(단일 객체 생성 시 생성자 호출) 포인터가 가리키는 객체의 소멸자를 호출 후 메모리 반환
배열 형식 new Type[n] (배열 할당) delete[] ptr (배열 해제)
메모리 정렬 구현에 따라 기본 정렬을 따름(필요 시 alignas 사용) 동일한 정렬 요구사항을 만족하는 메모리 해제

문법

// 단일 객체
Type* p = new Type(args...);   // 생성자 호출
// 배열
Type* arr = new Type[count];   // 기본 생성자 호출(또는 POD인 경우 초기화되지 않음)

// 해제
delete p;                     // 소멸자 호출 후 메모리 반환
delete[] arr;                 // 배열 소멸자 호출 후 메모리 반환
  • new 연산자는 operator new 함수를 내부적으로 호출한다. 표준에서는 전역 operator new(std::size_t)와 operator new[](std::size_t)를 제공한다. 사용자는 이 함수를 오버로드하여 커스텀 할당 전략을 정의할 수 있다.
  • delete 연산자는 대응되는 operator delete와 operator delete[]를 호출한다. 오버로드된 경우, 동일한 형태(단일/배열)와 일치해야 한다.

예외 처리

try {
    Widget* w = new Widget();   // 할당 실패 시 std::bad_alloc 발생
} catch (const std::bad_alloc& e) {
    // 예외 처리
}

예외를 비활성화하려면 std::nothrow를 사용할 수 있다.

Widget* w = new (std::nothrow) Widget();   // 할당 실패 시 nullptr 반환

주의점

  1. new와 delete는 반드시 짝을 이루어야 한다. 짝이 맞지 않을 경우 메모리 누수 또는 이중 해제가 발생한다.
  2. delete에 nullptr를 전달하면 아무 동작도 수행되지 않는다(안전).
  3. new와 delete는 같은 할당자/해제자를 사용해야 한다. 전역 operator new와 사용자 정의 operator delete가 혼용되면 정의되지 않은 동작이 발생한다.
  4. 배열을 new로 할당했지만 delete(단일)로 해제하면 정의되지 않은 동작이다. 마찬가지로 new[]와 delete[]도 짝을 맞춰야 한다.

표준 규격

  • C++ 표준(ISO/IEC 14882)에서 new와 delete는 5.3.4(동적 메모리 할당) 및 5.3.5(동적 메모리 해제) 절에 정의돼 있다.
  • C++17부터 std::aligned_alloc과 std::aligned_new 같은 정렬 지원이 추가되었으며, C++20에서는 operator new의 nothrow_t 및 align_val_t 오버로드가 공식화되었다.

관련 연산자 및 함수

이름 설명
std::nothrow 할당 실패 시 예외 대신 nullptr을 반환하도록 new에 전달
std::unique_ptr<T> RAII 기반 자동 해제를 제공, new와 delete 사용을 대체 가능
std::shared_ptr<T> 공유 소유권을 제공, 내부적으로 delete를 호출
operator new / operator delete 전역 또는 클래스 별 오버로드 가능한 메모리 할당/해제 함수
placement new 기존 메모리 영역에 객체를 생성(소멸자는 별도 호출 필요)

역사 및 어원

  • new와 delete는 C++ 초기 설계 시점(1980년대 후반)부터 포함되었다. C 언어의 malloc/free와 달리 객체 생성·소멸자를 자동으로 연계하도록 설계되었다.
  • 용어 자체는 영어 동사 ‘new(새로운)’와 ‘delete(삭제하다)’에서 차용된 것으로, 메모리 관리 연산자를 직관적으로 표현한다는 의도다.

실제 사용 예시

#include <iostream>

class Node {
public:
    int value;
    Node(int v) : value(v) { std::cout << "Node constructed
"; }
    ~Node() { std::cout << "Node destroyed
"; }
};

int main() {
    Node* p = new Node(10);    // 생성자 호출, 메모리 할당
    std::cout << p->value << '
';
    delete p;                  // 소멸자 호출, 메모리 반환

    // 배열
    Node* arr = new Node[3] { {1}, {2}, {3} };
    delete[] arr;
    return 0;
}

요약
new와 delete는 C++ 표준에 포함된 핵심 메모리 관리 연산자로, 동적 객체 생성을 위한 할당과 소멸자를 포함한 해제를 담당한다. 올바른 짝 맞춤, 예외 처리, 그리고 필요 시 사용자 정의 operator new/delete를 통해 다양한 메모리 관리 전략을 구현할 수 있다.

(본 내용은 ISO/IEC 14882 표준 및 널리 인정받는 C++ 교과서·문서에 기반함)

둘러보기

더 찾아볼 만한 주제

    전체 문서 보기