프로그래밍C++ 개발자, 시스템 프로그래머

C++에서 operator new/operator delete 메커니즘에 대해 설명해 주세요. new/delete와는 어떻게 다르며, 사용자 클래스에서 연산자 함수를 재정의하는 이유와 시점은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

C++에서 operator newoperator deletenewdelete 연산자를 통해 객체를 할당하고 해제할 때 호출되는 메모리 할당 및 해제 함수입니다. 기본적으로 표준 할당자를 사용하지만, 클래스 내에서 메모리 할당을 세밀하게 제어하기 위해 재정의할 수 있습니다.

  • operator new는 생성자를 호출하지 않고 "원시" 메모리 영역을 할당합니다.
  • 메모리를 할당한 후에 자동으로 객체의 생성자가 호출됩니다.
  • operator delete는 객체의 소멸자가 완료된 후 메모리를 해제합니다.

사용 (전역 및 지역 버전):

  • 전역 버전은 기본적으로 적용됩니다 (예: new int).
  • 특정 operator new를 클래스 내에서 재정의하면 해당 클래스의 객체에 대한 메모리 작업을 최적화할 수 있습니다 (예: 객체 풀, 추적, 블록 재사용).

operator new/operator delete 오버로딩 예:

#include <iostream> class TrackAlloc { public: void* operator new(size_t size) { std::cout << "TrackAlloc::new for " << size << " bytes "; return ::operator new(size); } void operator delete(void* ptr) { std::cout << "TrackAlloc::delete "; ::operator delete(ptr); } };

주의사항:

  • 인수를 가진 객체의 생성/삭제(위치 new 호출)는 별도의 오버로딩이 필요합니다.
  • 재정의된 연산자는 클래스의 객체 생성/삭제에만 호출되며 new[]/delete[]에는 호출되지 않습니다. 이들을 위해 별도의 operator new[]/delete[]를 오버로딩할 수 있습니다.
  • 메모리 조작은 위험합니다 — 예외 처리를 적절히 해야 합니다.

함정 질문.

"클래스에서 operator new를 재정의하고, 그 후에 상속된 클래스의 변수를 통해 객체를 생성하면 어떻게 되나요? 어떤 버전의 operator new가 호출될까요?"

답변: 객체를 생성하는 기명의 클래스의 operator new가 호출됩니다. 만약 파생 클래스에 operator new가 구현되어 있지 않다면, 적절한 버전을 기본 클래스에서 찾거나 전역 버전을 사용하게 됩니다.

예:

struct Base { void* operator new(size_t s) { std::cout << "Base new "; return ::operator new(s); } }; struct Derived : Base {}; Derived* p = new Derived; // Base::operator new! 호출됨

주제의 세부사항을 모르고 발생한 실제 오류 예시.


역사

개발자들은 예외 처리를 위한 지원 없이 operator new/ delete를 오버로딩했습니다. 생성자 내에서 예외가 발생할 경우 메모리가 해제되지 않아 메모리 누수가 발생했습니다.


역사

operator new[] 및 operator delete[]를 잘못 구현하여, 배열을 포함한 클래스 내에서 새로운 구현이 호출되지 않고 기본 버전이 사용되었으며, 이는 메모리 할당 및 해제 로직의 비동기화를 초래했습니다.


역사

전역 operator new의 재정의가 외부 라이브러리의 작업에 영향을 미쳐 모든 객체(임시 객체 및 STL 객체 포함)가 로깅할당자를 통해 할당되었고, 이는 애플리케이션의 핵심 작업을 비정상적으로 느리게 만들었습니다.