c++ allocator

jw kim·2022년 7월 26일
0

allocator, 왜사용하는가.

allocator 클래스는 주로 표준 라이브러리의 컨테이너를 구현할 때 많이 사용된다.
메모리 관리를 좀 더 세밀하게 컨트롤, 유연하고 효율적으로 사용해아 할 경우에 유저가 원하는 메모리 할당 방식으로 구현할 수 있다.

컨테이너는 메모리를 최대한 효율적으로 관리할 수 있어야 하는데 new/delete 연산자로는 세밀한 메모리 관리능력이 떨어진다.

c++ 에서 클래스타입이 new 연산자를 사용하는데 필요한 조건은 세가지다.
1. 기본 생성자
2. 메모리 할당
3. 초기화

int a = 3; 이라는 코드는
1. int a = 0; 할당
2. int a = 3; 초기화 두 단게를 거친다.

allocator 클래스를 사용하면 위 단계들을 각각 원할 때 사용할 수 있다.

template <class T>
class allocator
{
public:
	T* allocate(size_t);
    void deallocate(T*, const T&);
    void construct(T*, const T&);
    void destroy(T*);
    ...
};

template <class In, class For>
ForwardIterator uninitialized_copy(InputIterator firtst, InputIterator last, ForwardIterator result);

template <class For, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);

T* allocate(size_t); 함수는 초기화되지 않은 메모리 공간을 할당, 그 시작 주소를 반환하는 함수다.
매개변수 size_t 는 바이트단위가 아니라 T객체의 갯수며, 인자로 전달된 개수 만큼 T타입 객체를 할당후 4바이트만큼 공간을 할당해준다.
예를 들어 8바이트 타입의 객체를 5개 저장하고자 allocate 함수를 호출하면 8byte * 5 + 4bytes 인 44bytes 가 할당되고 그 시작 주소를 반환한다.

void deallocate(T*, const T&); deallocate 함수는 메모리 공간을 해제하는 함수다.
인자로 포인터와 갯수를 받으며 포인터는 allocate로 할당했던 메모리의 시작 주소를 가리키는 포인터이며 갯수는 allocate로 전달했던 인자의 갯수다. (근데 allocate시에 입력했던 n 개의 숫자가 아니라 다른 수를 입력해도 메모리 상에서 지워지기는 하나보다..)

void construct(T*, const T&); 함수는 초기화되지 않은 공간에 요소를 저장하는 함수다.
T 타입 포인터와 객체를 래퍼런스로 받으며 포인터가 가리키는 위치에 객체를 저장한다. 초기화되지 않은 공간에 *(간접참조) 연산자를 사용하여 값을 대입할 경우 에러가 발생한다.

void destroy(T*); 함수는 객체를 소멸시킨다.
소멸과 메모리해제는 다르다. T 타입 포인터를 인자로 받으며 포인터가 가리키는 위치의 객체의 소멸자를 호출한다. 즉 인자로 전달된 포인터가 가리키는 객체의 소멸자를 호출한다. destroy를 호출하지 않고 deallocate를 호출할 경우 각 요소에 저장된 객체는 사라지겠지만 사라진 객체가 가리키던 객체는 그대로 메모리에 남아있어 메모리 누수가 발생할 수 있다.

ForwardIterator uninitialized_copy(InputIterator firtst, InputIterator last, ForwardIterator result) 함수는 멤버 함수는 아니지만 자주 사용되는 함수다.
STL의 std::copy함수와 비슷하며 입력반복자 2개(first, last)와 순방향 반복자 1개(out)를 인자로 받는다. first ~ last 범위의 요소들을 out 이 가리키는 위치에 순서대로 복사한다. 그리고 이 함수는 복사가 완료된 위치에 다음 요소를 가리키는 포인터를 반환한다. 즉 1~5위치에 복사를 완료했다면 6위치를 가리키는 포인터를 반환한다.

void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); 함수는 주어진 범위의 공간을 3번째 인자로 주어진 값으로 채운다.

profile
Hitchhiker

0개의 댓글