[Rank 5] ft_containers - Allocator
Allocator 클래스

컨테이너를 하기 위해 필수로 알아야 하는 클래스이다
앞의 반복자 파트에서는 전혀 쓸 일이 없었지만 벡터나 스택 같은 컨테이너들은 기본적으로 메모리 할당을 하고 그 안에 요소들을 저장해야 하며, 내부 메서드에서 메모리 일부 할당 및 해제가 잦기 때문에 Allocator의 사용법을 반드시 익혀야 한다
뭐 하는 녀석인지
C/C++에서는 메모리 관리를 위해서 malloc, calloc, free … 와 new, delete를 사용했었다
특정 변수를 위한 메모리를 할당하고자 한다면 이 함수들이 편리하지만, 직접 컨테이너를 구현할 때 (ft_containers 처럼) 는 이야기가 달라진다
컨테이너 내부에서는 특정 메서드를 호출할 때마다 일정 영역만 메모리를 해제하거나 재할당하는 등 다양하고 세밀한 동작을 요구하므로, new / delete 만으로는 한계가 있는 것이다
예를 들면, 벡터의 용량 (capacity) 을 늘리거나 줄일 때 (reserve), 벡터의 크기 (size) 를 늘릴 때 (resize) 는 인자로 받은 크기만큼 메모리를 재할당해 주어야 하는데, new 만으로는 이러한 조작이 애매해진다
new는 메모리 할당 뿐만 아니라 초기화도 동시에 진행하므로, 메서드를 통해 new를 자주 호출하게 되면 성능의 저하도 발생할 것이다

컨테이너를 만들기 위해선 allocator 를 쓰자
Allocator 클래스 구문
template <class T>
class allocator
- 템플릿 클래스로, 어떤 자료형 (클래스) 의 메모리 공간을 할당 / 해제할 것인지 나타내는 클래스
T를 갖는다 allocator는<memory>헤더를 include하여 사용할 수 있다
타입 정의
pointer
T의 포인터 타입이다
reference
T의 참조 타입이다
const_pointer
T의 상수 포인터 (constant pointer) 타입이다
const_reference
T의 상수 참조 (constant reference) 타입이다
size_type
unsigned int 형식으로, allocator가 할당할 수 있는 메모리 영역의 단위 길이를 나타낸다
value_type
allocator가 다루는 타입으로, T와 같다
멤버 함수
생성자
allocator(); // 생성자
allocator(const allocator<T>& instance); // 복사 생성자
template <class T_>
allocator(const allocator<T_>& instance); // 복사 생성자
- 새로운
allocator객체를 생성한다
address
pointer address(reference val) const;
const_pointer address(const_reference val) const;
- 인자로 들어온 요소
val의 주소를 반환한다
allocate
pointer allocate(size_type count, const void* _Hint = 0);
count개의T타입 메모리 영역을 새롭게 할당한다 (메모리 크기:count*sizeof(T))_Hint는 근처의 메모리 주소를 넣을 수 있으며, 특정 주소의 근처에 새로운 메모리를 할당하고 싶다면 힌트로서 메서드에 제공할 수 있다_Hint의 기본값은 0 (널 포인터) 이므로, 굳이 2번째 인자를 제공하지 않아도 자동으로 초기화된다_Hint가 제공되면, 최대한 해당 주소에 가까운 곳에 새로운 메모리를 할당한다
- 반환값 (
pointer타입) 은 새롭게 할당한 메모리 영역의 첫 번째 요소 주소이다
construct
void construct(pointer p, const_reference val);
- 메모리는 할당되었지만 초기화되지 않은 메모리 주소
p에T타입의 객체를 생성 (Construct) 한다 - 주소
p에new키워드를 이용하여T생성자를 호출한 것과 똑같이 동작한다- 생성자의 인자로
val이 들어간다 (복사 생성자 호출) new((void *)p) T(val)과 동작이 같다
- 생성자의 인자로
deallocate
void deallocate(pointer p, size_type n);
- 메모리 주소
p가 가리키는 영역을 해제한다- 주소
p부터 총n개의T타입 메모리 영역을 해제한다 (메모리 크기:n*sizeof(T))
- 주소
- 다만 이 함수를 호출하는 것이 내부에 초기화된 객체의 소멸자를 호출하지 않음에 주의하자
destroy
void destroy(pointer p);
- 메모리 주소
p가 가리키는 영역의 소멸자를 호출한다 deallocate와 반대로, 이 함수는 메모리 영역 해제를 도와주진 않는다
max_size
size_type max_size() const throw();
- 현재 할당 가능한
T타입의 메모리 개수allocate등에서 사용되는count의 최대값으로, 이 이상의 메모리를 할당받을 수 없다allocate(count, 0)이 성공할 수 있는count의 최대값이라고 이해하자
비 멤버 함수
operator==
template <class T1, class T2>
bool operator==(const allocator<T1>& lhs, const allocator<T2>& rhs) throw();
==연산자에 대한 오버로드- 두
allocator인스턴스를 비교하…긴 하는데, 기본allocator는 무상태성을 띄므로 결과적으로 모든allocator는 같다- 따라서 항상
true를 반환한다
- 따라서 항상
operator!=
template <class T1, class T2>
bool operator!=(const allocator<T1>& lhs, const allocator<T2>& rhs) throw();
!=연산자에 대한 오버로드==오버로드와 마찬가지로,allocator의 무상태성 때문에 모든allocator이 같음을 보장한다- 따라서 항상
false를 반환한다
- 따라서 항상
참고 자료
https://en.cppreference.com/w/cpp/memory/allocator
https://cplusplus.com/reference/memory/allocator/
https://learn.microsoft.com/en-gb/cpp/standard-library/allocator-class?view=msvc-170#address