-
Effective C++...49일지 2022. 8. 28. 13:00
new 및 delete를 작성할 때 따라야 할 기존의 관례를 잘 알아 두자
operator new의 관례
new는 몇 가지 관례가 존재하는데 먼저 0바이트가 요구되었을 때도 적법한 포인터를 반환해야 한다는 것이다.
이에 대해서는 0바이트가 요구될 때는 1바이트로 가정해서 작업을 진행한다.
void* operator new(std::size_t size) throw(std::bad_alloc)
{
using namespace std;
if (size == 0) {
size = 1;
}
while(true) {
if (할당 성공)
return 할당된 메모리의 포인터;
// 할당 실패 시 new 처리자 함수가 있으면 그것을 실행, 아니면 bad_alloc 예외를 발생시킨다.
}
}
또, operator new에는 무한 루프가 들어가서 두 번 이상 할당을 시도하게 되는데 위의 함수에서 while(true) 부분에서 확인할 수 있다.
※ 무한 루프에 갇히지 않기 위해서는 new 처리자 함수 쪽에서는 네 가지 동작 중 하나를 반드시 해 줘야 한다.
operator new가 파생되었을 때 Base클래스와 Derived클래스의 크기가 다르다면 operator new가 정상적으로 동작하지 않을 수 있다. 따라서 크기를 검사해서 크기가 다르면 기존의 operator new를 호출해줘야 한다.
void* Base::operator new(std::size_t size) throw(std::bad_alloc)
{
if (size != sizeof(Base))
return ::operator new(size);
...
}
operator delete의 관례
C++에서는 널 포인터에 대한 delete 적용이 항상 안전해야 한다는 것 외에는 크게 관례가 존재하지 않는다.
void operator delete(void* rawMemory) throw()
{
if (rawMemory == 0) return;
...
}
가상 소멸자가 없는 기본 클래스에서 파생된 클래스를 제거할 때 operator delete로 전달되는 size가 엉망일 수 있다. 따라서 클래스를 파생시킬 때는 반드시 가상 소멸자를 사용해야 한다.