메모리를 단순 new, delete
로 관리하지말고 미리 Allocate해둔 후 관리해 보자.
왜 그렇게 해야할까?
- 우선 Windows기반에서는 메모리관리를 OS에서 해준다.
- 할당해야할 메모리가 많아진다면 OS의 커널영역에서 새로운 메모리 할당을 하며 컨텍스트 스위칭비용이 발생하는데 그 비용을 감소시키기 위함이 있고
-
또한 메모리 파편화 현상을 방지하는데 내가 메모리를 Allocate해서 관리하면 좋기 때문이다.
- 우선 이번강에서는 위 문제를 해결한순 없다. 단,
new, delete
를 이렇게 개발자가 커스터마이징 가능하다는 것을 이해하자
그럼 구현을 해보자.
우선 new
와 delete
를 개발자가 새로 구현해야한다.
// new, delete를 어떻게 커스터마이징 할까
// new operator overloading (Global)
void* operator new(size_t size)
{
cout << "new! " << size << endl;
void* ptr = ::malloc(size);
return ptr;
}
void operator delete(void* ptr)
{
cout << "delete!" << endl;
::free(ptr);
}
void* operator new[](size_t size)
{
cout << "new[]! " << size << endl;
void* ptr = ::malloc(size);
return ptr;
}
void operator delete[](void* ptr)
{
cout << "delete![]" << endl;
::free(ptr);
}
// 생각보다 간단...
// 단, 이렇게 전역으로 구현하면 의도치 않은 new와 delete에도 영향을 줄 수 있다.
class Knight
{
public:
Knight()
{
cout << "Knight()" << endl;
}
Knight(int32 hp) : _hp(hp)
{
cout << "Knight(hp)" << endl;
}
~Knight()
{
cout << "~Knight()" << endl;
}
// 이렇게 객체안에 넣어서도 구현가능
static void* operator new(size_t size)
{
cout << "Knight new! " << size << endl;
void* ptr = ::malloc(size);
return ptr;
}
static void operator delete(void* ptr)
{
cout << "Knight delete!" << endl;
::free(ptr);
}
int32 _hp = 100;
int32 _mp = 10;
};
그럼 매번 클래스 안에 new, delete를 구현해야 할까?
해결해보자
// 새로운 new, delete를 만들어 보자
#ifdef _DEBUG
#define xalloc(size) BaseAllocator::Alloc(size)
#define xrelease(ptr) BaseAllocator::Release(ptr)
#else
#define xalloc(size) BaseAllocator::Alloc(size)
#define xrelease(ptr) BaseAllocator::Release(ptr)
#endif
void* BaseAllocator::Alloc(int32 size)
{
return ::malloc(size);
}
void BaseAllocator::Release(void* ptr)
{
::free(ptr);
}
#pragma once
#include "Allocator.h"
template<typename Type, typename... Args>
Type* xnew(Args&&... args)
{
Type* memory = static_cast<Type*>(xalloc(sizeof(Type)));
new(memory)Type(forward<Args>(args)...); // placement new - 여기가 헷갈린다(지연 생성)
// new(memory) : 메모리는 이미할당되어 있으니 할당하지말고
// Type(forward<Args>(args)...) : 요렇게 생성자만 호출해 줘
return memory;
}
template<typename Type>
void xdelete(Type* obj)
{
obj->~Type();
xrelease(obj);
}
실사용은 이렇게
int main()
{
Knight* knight = xnew<Knight>(100);
xdelete(knight);
}