[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" new와 delete는 언제나 짝을 이루어야 한다! "
- operator new 함수의 위치지정 버전을 만들 때는 이 함수와 짝을 이루는 위치지정 버전의 operator delete 함수도 꼭 만들자. 이 일을 빼먹었다간 찾아내기도 힘들며 또 생겼다가 안 생겼다 하는 메모리 누출 현상을 경험하고 된다!
- new 및 delete의 위치지정 버전을 선언할 때는 의도한 바도 아닌데 이들의 표준 버전이 가려지는 일이 생기지 않도록 주의 하자!
operator new
, operator delete
의 기본형과 달리 매개변수를 추가로 받는 형태의 함수를 위치지정 new, 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, 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();
...
};