

std::allocator<T>
C++ 표준 라이브러리에서 제공하는 기본 메모리 할당자로, 주로 STL 컨테이너에서 내부적으로 메모리 관리를 위해 사용된다. 메모리 관리를 좀 더 세밀하게 컨트롤 해야하고 유연하고 효율적으로 사용해야 할 경우, 오버라이드를 통해 유저가 원하는 메모리 할당 방식으로 구현할 수 있다.
클래스 타입이라는 가정하에 new
연산자를 사용하게 되면 필수적으로 따라오는 3가지 조건이 있다.
기본 생성자 필요
메모리 할당
모든 요소 초기화
new
연산자는 라이브러리 개발자가 원하는 메모리 할당 방식으로 커스터마이징 할 수 없는데, allocator
클래스를 사용하면 위 단계들을 각각 원할 때 사용할 수 있다.
_EXPORT_STD template <class _Ty, class _Alloc = allocator<_Ty>>
class vector
대표적인 컨테이너인 vector
를 사용할 때, 우리는 보통 타입 매개변수 하나만 전달한다. 하지만 코드를 보면 알 수 있듯, 기본 매개변수로 allocator
가 사용되고 있다. 특정 컨테이너에 최적화된 유연한 메모리 사용과 관리를 위해, 대부분의 컨테이너들은 allocator
를 사용하는 것이다.
좋은 점
클래스 타입의 요소를 갖는 크기 10의 벡터를 선언했다고 가정해보자. 만약 내부적으로 벡터가 new 연산자를 통해 생성된다면, 벡터는 할당과 동시에 모든 요소들이 기본 생성자를 통해 초기화 되어있을 것이다. 그리고 사용자가 이 벡터에 원하는 요소를 저장하면, 각 요소들을 두번씩 초기화하게 될 것이다.
만약 allocator
의 멤버 함수를 이용하면, 메모리의 할당은 되었지만 초기화 되지 않은 상태의 메모리의 시작 주소를 얻을 수 있다. 원래 초기화되지 않은 메모리 공간에 객체를 직접 할당할 수 없지만, 해당 클래스의 멤버 함수 또는 관련 함수가 초기화 되지 않은 공간에 객체를 저장할 수 있도록 해준다.
그리고 할당받은 메모리에 객체를 생성 후, 메모리 해제 없이 생성한 객체들을 소멸시킬 수 있다. 즉, 메모리의 재할당 없이 그 공간을 allocate
했던 초기 상태로 만들 수 있다는 소리이다. 또한 해당 라이브러리는 할당받은 메모리 공간 중 객체가 생성된 공간과 아직 초기화되지 않은 공간을 알 수 있는 방법을 제공한다.
allocator
template <class T>
class allocator
{
public:
T* allocate(size_t);
void deallocate(T*, size_t);
void construct(T*, const T&);
void destory(T*);
....
};
template <class In, class For>
For uninitialized_copy(In, In, For);
template <class For, class T>
void uninitialized_fill(For, For, const T&);
allocator
클래스는 주로 4개의 멤버 함수와 멤버 함수는 아니지만 용도에 따라 관련된 함수 2개를 사용한다.
allocate(size_t)
: 초기화되지 않은 메모리 공간을 할당하여 그 시작 주소를 반환하는 함수. 매개변수는 필요한 T 객체의 개수이며, 인자로 전달된 개수만큼 T타입의 객체를 충분히 할당할 수 있는 공간을 만든다.deallocate(T*, size_t)
: 메모리 공간을 해제하는 함수. 인자로 포인터와 개수를 받는다. 포인터는 allocate로 할당했던 메모리의 시작 주소를 가리키는 포인터이며, 개수는 allocate로 전달했던 인자의 개수이다.construct(T*, const T&)
: 초기화되지 않은 공간에 요소를 저장하는 함수. T타입 포인터와 객체를 레퍼런스로 받으며 포인터가 가리키는 위치에 객체를 저장한다. 초기화되지 않은 공간에*
연산자를 사용하여 값을 대입할 경우 에러가 발생하는데, 이 함수를 통해 에러없이 저장할 수 있다.destory(T*)
: 객체를 소멸시키는 함수. 소멸과 메모리 해제는 다르다. 인자로 전달된 포인터가 가리키는 객체의 소멸자를 호출한다.destroy
를 호출하지 않고deallocate
를 호출할 경우, 각 요소에 저장된 객체는 사라지겠지만 사라진 객체가 가리키던 객체는 그대로 메모리에 남아있어 메모리 누수가 발생할 수 있다.uninitialized_copy(In, In, For)
: 초기화되지 않은 메모리 영역에 있는 객체들을 복사하여 새롭게 초기화하는 데 사용된다. 복사할 객체들이 위치한 입력 범위의 시작과 끝을 나타내는 반복자 2개(first, last)와 객체를 복사하여 생성할 대상 메모리의 시작 주소를 나타내는 순방향 반복자 1개(out)를 인자로 받는다. [first, last) 범위의 요소들을 out이 가리키는 위치에 순서대로 복사하고, 복사가 완료된 위치의 다음 요소를 가리키는 포인터를 반환한다.uninitialized_fill
: 주어진 범위의 공간을 3번째 인자로 주어진 값으로 채운다.