C++에서 operator new와 operator delete는 new와 delete 연산자를 통해 객체를 할당하고 해제할 때 호출되는 메모리 할당 및 해제 함수입니다. 기본적으로 표준 할당자를 사용하지만, 클래스 내에서 메모리 할당을 세밀하게 제어하기 위해 재정의할 수 있습니다.
operator new는 생성자를 호출하지 않고 "원시" 메모리 영역을 할당합니다.operator delete는 객체의 소멸자가 완료된 후 메모리를 해제합니다.operator new를 클래스 내에서 재정의하면 해당 클래스의 객체에 대한 메모리 작업을 최적화할 수 있습니다 (예: 객체 풀, 추적, 블록 재사용).#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); } };
"클래스에서 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 객체 포함)가 로깅할당자를 통해 할당되었고, 이는 애플리케이션의 핵심 작업을 비정상적으로 느리게 만들었습니다.