이번 항목은 new 에 대한 설명이다.

1 ) C++ 표준에 있는 new의 세 가지 형태는 무엇인가?

보통 new(new), 비투척 new(notrow new), 위치지정 new(placement new) 이렇게 있다. 아래 표를 보자

 표준 new들

추가적인 매개변수

할당 수행

실패 가능

예외 던짐

 교체가능

 보통 new
 없음  예  예(예외 던짐)
 std::bad_alloc  예
 비투척 new
 std::nothrow_t  예  예(널 반환)
 아니요  예
 위치지정 new
 void*  아니요  아니요  아니요  아니요

한가지 신기한 것은 위치지정 new 의 경우, 메모리 할당을 수행하지 않는 다는 것! 이다. 위치지정 new의 경우, 그 자리에 생성자를 실생 시키는 역활을 수행한다.


2 ) 클래스에 고유한 new는 무엇이며, 어떻게 사용하는가? 독자가 클래스에 고유한 new와 delete를 만들 때 특별히 신경 써야 할 부분들을 서술하라.

클래스 고유 new 와 이를 어떻게 사용 하는가?

표준 new 3개는, 전역 함수들이다. 이를 특정 클래스에 멤버 함수로 정의하여 사용 할 수 있는데, 이런 new 들을 클래스에 고유한 new라고 한다. 위의 표에서 위치지정 new(placement new)의 경우, 교체가 불가능한데, 클래스에 한해서는 교체가 가능하다.

다음의 코드처럼 new를 정의하고 사용 한다.


3번의 경우, ::operator (void*) new 를 대체하지 않고, 클래스의 operator (void*) new 를 정의함으로써, 클래스 전용일 때, 교체가 되는 것을 확인 할 수 있을 것이다.


특히 신경 써야 할 부분이 무엇인가?

많이 있다. 그 중에 이름 "이름 가림 문제"부터 신경써야 하지 않을까 한다.


3 ) 다음 코드에서, 1에서 4까지의 줄들이 호출하는 operator new는 각각 어떤 것인가?


먼저 알아야 될 것은 이름 검색 규칙이다. 이름 검색(Koening Lookup) 규칙 : "현재 범위에서 이름을 찾고, 없다면, 다음 범위로 넘어 간다. 만약 지금 검색하는 범위에서 이름을 찾았다면, 다음 범위로의 검색을 중지하고, 지금 검색하는 범위에서 중복적재 해소(오버로딩)를 하고, 남은 마지막 하나가, 지명된 이름이다."

클래스 고유 new를 호출 하려 할 때도 이 방법이 사용 되는데, Derived::operator new를 발견하고, 지금 범위에서 검색을 중단 한다.

그래서 1,2,3,4 의 이름 검색에서, 1,2,3 의 Derived::operator new 는 정의 되어 있지 않기 때문에, 컴파일 오류가 발생한다. 함수를 찾을수 없다고 말이다. 그리고 4번은 Base::operator new 가 호출 된다.

이 문제의 해결 방법으로는, "단 하나라도 클래스 고유 버전의 new가 있다면, 모든 operator new 들을 클래스 고유 버전으로 정의해야 한다."

클래스 고유 버전 new 들을 구현함에 있어, 특별한 처리가 필요한게 아니라면, 전역 버전을 수단으로 구현하는게 좋다. 예외 명세 역시 따라 주는게 좋다. (특정 컴파일러에선 예외 명세가 안될 수 있다.)

여기서 한가지 중요한 사실이 있다. 바로 표준 컨테이너에 처박히게 하고 싶다면, 표준 placement new와 같은 서명(signature)을 가진 클래스 고유 placement new 제공해 주어야 한다는 것이다. 왜냐하면, 표준 컨테이너는 처박을 때, 표준 placement new 를 사용 하기 때문이다.


총평

operator new 를 재정의 하고 싶다면, 이름 가림 문제 말고도, 0바이트 문제, 상속에 따른 구현 문제 등이 있다.. .. 그것들 때문에 막상 정의하기가 꺼려진다. ^^

posted by 농사를 짓는 게임 프로그래머 최익필

댓글을 달아 주세요