언리얼의 대표 컨테이너 라이브러리에는 TArray, TMap, TSet이 있다.
줄여서 UCL이라고 불리기도 하는 이들은 언리얼 오브젝트들을 안정적으로 지원을 해준다.
그냥 C++ STL의 컨테이너들과 무엇이 다를까?
STL은 범용성이 높게 설계되어있기 때문에 한번 컴파일 하는데 시간이 오래 걸리게 된다.
언리얼은 언리얼에서 제공하는 오브젝트만 안정적으로 지원을 하고 최대한 효율을 뽑아내야하기 때문에 게임 제작에 최적화 되어 있다고 생각하면 된다.
조금 더 자세히 알아보자
언리얼의 가장 간단하고 가장 많이 쓰게 되는 컨테이너 클래스라고 할 수 있다.
가변 배열 자료구조로써, STL의 Vector와 비슷하다고 생각하면 된다.
데이터가 메모리에 모여있기 때문에 캐시 지역성으로 인한 성능 향상에 유리하다.
하지만 가변 배열의 단점으로써, 중간에 요소를 추가하거나 삭제하는 작업의 비용이 비교적 크다.
데이터가 많아지면 검색, 삭제, 수정 등의 작업이 느려지기 때문에 데이터가 방대한데 검색 작업이 빈번하다면 TArray 대신 TSet 사용을 고려해보는 것도 좋다.
TArray는 밸류 타입이기 때문에 동적 할당을 하는 것은 좋지 않다는 것을 명심하자.
TArray에 값을 넣는 방법은 Add와 Emplace가 있는 데, Emplace의 효율이 더 좋다고 한다. 근데 Add은 가독성이 좋으니 간단한 작업에 쓴다고 한다.
TSet은 STL의 Set과는 다르게 해시테이블 형태로 키 데이터가 구축되어 있어서 서로 활용 용도가 다르다.
(STL은 이진 트리로 구성)
TSet은 독립된 키로 데이터 값을 연결하기 보다는 데이터 값 자체를 키로 사용하며 중복을 허용하지 않는다.
언리얼에서 제공하는 것이 아닌 독자적인 커스텀 타입을 만들어서 사용할 시, GetTypeHash
라는 함수를 만들어서 해시를 만들 수 있게 해야 사용 가능하다. 그리고 동일성 비교를 위한 operator ==를 만들어야한다.
TSet은 검색도 빠르고 추가, 삭제할 때도 재구축이 일어나지 않아서 빠르게 사용하기 좋다.
대신 재구축이 일어나지 않는 만큼, 비어있는 데이터가 발생할 수도 있다.
비어있는 공간에는 다음에 들어오게 될 데이터가 자리하게 된다.
TSet은 인덱스로 사용이 가능은 하지만 권장은 하고있지 않다.
위와같이 데이터가 들어오면 Set의 순서를 모두 파악하고 있기 쉽지 않기 때문도 있을 것이다.
TArray 다음으로 자주 쓰이는 컨테이너이다.
TSet 구조로 되어있으며 다른 점은 키, 밸류 구성의 튜플 데이터를 가진다는 점이다.
내부적으로 TPair<Key, Element>
이런 오브젝트로 구성이 되어 있다고 생각하면 된다.
TMultiMap을 사용하면 중복을 허용할 수 있다.
기본적으로 해시 테이블 구조로 관리하기 떄문에 커스텀 데이터 자료 구조를 만들 때는 이 구조체에 해시 값을 만들어주어야한다고 위 TSet에서 알아보았다.
근데 여기서 특이한 경우가 발생하는데,
기본적으로 멤버변수에 ID와 프로퍼티가 존재할 때, 내용물은 같은데 ID만 다를때는 이 구조체가 서로 같다고 보기 힘들다.
TMap에서는 중복을 허용하지 않지만 ID를 제외하고서는 같은 구조체이기 때문에 이를 어떻게 처리를 해야할지 고민에 빠지는 상황이 생길 수 있다는 뜻이다.
이런 경우에 추가적으로 ==에 대해서 정의를 해주어야 할 필요가 있을 때가 있다.
이 때 사용하라고 만들어 둔 것들이 있는데, 바로 KeyFuncs이다.
과연 이런 상황을 얼마나 마주칠까는 모르겠는데 알아두면 좋지 않을까 싶다.