일지

Effective C++...49

niamdank 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가 엉망일 수 있다. 따라서 클래스를 파생시킬 때는 반드시 가상 소멸자를 사용해야 한다.