[ Effective C++ ] 항목 52 : 위치지정 new를 작성한다면 위치지정 delete도 같이 준비하자

Minsu._.Lighting·2023년 12월 16일
0

[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "

[핵심]

" new와 delete는 언제나 짝을 이루어야 한다! "

  • operator new 함수의 위치지정 버전을 만들 때는 이 함수와 짝을 이루는 위치지정 버전의 operator delete 함수도 꼭 만들자. 이 일을 빼먹었다간 찾아내기도 힘들며 또 생겼다가 안 생겼다 하는 메모리 누출 현상을 경험하고 된다!
  • new 및 delete의 위치지정 버전을 선언할 때는 의도한 바도 아닌데 이들의 표준 버전이 가려지는 일이 생기지 않도록 주의 하자!

💡 위치지정 new, delete

  • operator new, operator delete 의 기본형과 달리 매개변수를 추가로 받는 형태의 함수를 위치지정 new, delete라고 한다
    - 매개변수를 받는 new, delete는 가지각색일 수 있지만 그 중 특히 유용한 버전이 있는데, 어떤 객체의 메모리 위치를 나타내는 포인터를 매개변수로 받는 버전 이다.

📌 어떤 객체의 메모리 위치를 나타내는 포인터를 매개변수로 받는 operator new, operator delete

void* operator new(size_t, void* pMemory) throw();
void* operator delete(void*, ostream&) throw();
- 위치지정 new를 사용해 메모리를 할당했으나 그 후 예외가 발생해 delete를 호출해야 할 때 컴파일러는 사용한 new와 같은 버전의 delete를 찾는다!
- 그렇기에 new와 delete는 짝을 지어야 한다.

📢 만약 예외가 발생하지 않고 포인터에 delete를 적용했을 때는 절대로 위치지정 delete를 호출하지 않는다

Widget* pw = new (std::cerr) Widget;		// 해당 코드에서 예외 발생 시
											// 위치지정 delete 호출

delete pw;									// 해당 코드까지 닿으면
											// 기본 delete 호출

- 따라서 어떤 위치지정 new 함수와 조금이라도 연관된 모든 메모리 누출을 사전에 봉쇄하려면, 표준 형태의 delete를 기본으로 마련해 두고, 위치지정 new와 매개변수가 같은 delete도 구비해야 한다!

📌 위치지정 new, delete를 구현할 때 주의할 점

- 표준형태의 new, delte가 가려지지 않게 주의하자!

[ C++가 전역 유효 범위에 제공하는 operator new의 형태 ]

  • 기본 형태 new
    - void* operator new(size_t) throw(bad_alloc);
  • 위치지정 new
    - void* operator new(size_t, void*) throw();
  • 예외불가 new
    - void* operator new(size_t, const nothrow_t&) throw();

- 위 3가지 버전의 표준 형태들이 가려지지 않게 주의하자!

📢 클래스 전용 버전이 전역 버전을 호출하도록 구현하자!

class StandardNewDeleteForms
{
public:
	// 기본형 new, delete
    static void* operator new(size_t size) throw(bad_alloc)
    { return ::operator new(size); }
    
    static void operator delete(void* pMemory) throw()
    { ::operator delete(pMemory); }
    
    // 위치지정 new, delete
    static void* operator new(size_t size, void* ptr) throw()
    { return ::operator new(size, ptr); }
    
    static void operator delete(void* pMemory, void* ptr) throw()
    { ::operator delete(pMemory, ptr); }
    
    // 예외불가 new, delete
    static void* operator new(size_t size, const nothrow_t& nt) throw()
    { return ::operator new(size, nt); }
    
    static void operator delete(void* pMemory, const nothrow_t&) throw()
    { ::operator delete(pMemory); }
};

- 사용자 정의 형태를 추가하고 싶다면, 이 기본 클래스를 상속받아 파생 클래스를 만들어 using 선언을 사용해 주자

class Widget : public StandardNewDeleteForms
{
public:
	// 표준 형태가 가려지지 않게
	using StandardNewDeleteForms::operator new;
    using StandardNewDeleteForms::operator delete;
    
    // 사용자 정의 위치지정 new, delete
    static void* operator new(size_t size, ostream& logStream) throw(bad_alloc);
    
    static void* operator delete(void* pMemory, ostream& logStream) throw();
    ...
};
profile
오코완~😤😤

0개의 댓글

관련 채용 정보