new 연산자 오버로딩


new, delete 연산자의 오버로딩은 다른 연산자 오버로딩과 많이 다르다!!

이 둘은 분명 연산자이다. 따라서 연산자 오버로딩이 가능하며, 이 둘을 이용해서 클래스 별로 독특한 객체의 생성과정을 정의할 수도 있다. 그런데 이 둘에 대한 연산자 오버로딩은 이전에 보았던 연산자 오버로딩과는 다소 차이가 있다.


기본적으로 제공되는 new 연산자가 하는 일


1. 메모리 공간의 할당

2. 생성자의 호출

3. 할당하고자 하는 자료형에 맞게 반환된 주소 값의 형 변환


new 연산자가 진행하는 세 가지 작업 중에서 1번에 해당하는 메모리 공간의 할당만 오버로딩 할 수 있다,


다음과 같이 오버로딩 하도록 이미 약속이 되어있다

void* operator new(size_t size) {    }

반환형은 반드시 void 포인터 형이어야 하고, 매개변수는형은 size_t이어야 한다.


※ 일반적으로 size_t 는 다음과 같이 정의되어 있다.

typedef unsigned int size_t;

그래서 0 이상의 값을 표현할 목적으로 정의된 자료형이다.


※ 크기정보는 바이트 단위로 계산되어 전달된다.




delete 연산자 오버로


delete ptr; 이것의 문장으로 객체의 소멸을 명령하면,

컴파일러는 먼저 ptr이 가리키는 객체의 소멸자를 호출한다. 그리고는 다음의 형태로 정의된 함수에 ptr에 저장된 주소 값을 전달한다.

void operator delete(void* adr){    }


따라서 delete 함수는 다음의 형태로 정의해야 한다. 즉, 소멸자는 오버로딩 된 함수가 호출되기 전에 호출이 되니 오버로딩 된 함수에서는 메모리 공간의 소멸을 책임져야 한다. 


void operator delete(void* ptr)

{

delete []ptr;

}


참고로 사용하는 컴파일러에서 void 포인터 형 대상의 delete 연산을 허용하지 않는다면, 위의 delete문을 다음과 같이 작성하면 된다.

delete []((char*)adr);



19행; 컴파일러에 의해, 필요한 메모리 공간의 크기가 바이트 단위로 계산되어서 인자로 전달되니, 크기가 1바이트인 char 단위로 메모리 공간을 할당해서 반환한다. 


Point* ptr = new Point(3, 4);


아직 객체생성이 완성된 상태가 아닌데, 어떻게 멤버함수의 호출이 가능했을까?

그것은 operator new 함수와 operator delete 함수가 static 으로 선언된 함수이기 때문이다.

비록 멤버함수의 형태로 선언을 해도 이 둘은 static 함수로 간주가 된다. 그래서 객체생성의 과정에서 호출이 가능했던 것이다.






operator new & operator new[]


new 연산자는 다음 두 가지의 형태로 오버로딩이 가능하다.


void* operator new(size_t size){    }

void* operator new[](size_t  size){    }


두번째 함수는 new 연산자를 이용한 배열할당 시 호출되는 함수이다.

Point* arr  = new Point[3]; 이런 문장을 만나면,

컴파일러는 세 개의 Point객체에 필요한 메모리 공간을 바이트 단위로 계산해서, 이를 인자로 전달하면서 new[] 함수를 호출한다.

즉, 열할당 시 호출되는 함수라는 사실을 제외하고는 operator new 함수와 차이가 없다.


마찬가지로 delete 연산자도 다음 두 가지의 형태로 오버로딩이 가능하다.


void operator delete(void* adr){    }

void operator delete[](void* adr){    }


두 번째 함수는 delete 연산자를 이용한 배열소멸 시 호출되는 함수이다.

delete []arr;


58행:  객체로 구성된 배열이기 때문에 모든 객체의 소멸자가 호출된 다음에 36행에 정의된 멤버함수(static 함수)가 호출된다.



Posted by scii
: