본문 바로가기
게임 공부/Unreal Engine

[UE] TArray 컨테이너 클래스

by woohyeon 2021. 12. 26.
반응형

문법을 자세히는 다루지 않습니다. 오타나 틀린 부분이 있으면 알려주세요~


언리얼 엔진의 TArray는 C++의 std::vector와 비슷한 기능을 하는 동적 배열이다. 원소를 추가할 때 할당된 메모리 공간이 부족하면 자동으로 capacity를 늘려준다. 이 글의 목적은 vector에서 자주 사용하던 기능들을 TArray에선 어떻게 사용해야 하는지 간단하게 알아보는 것이다.

[초기화 관련]
TArray<T>는 std::vector<T>와 동일하게 템플릿 인자로 저장할 원소의 타입을 전달하여 선언하면, 해당 타입의 원소들을 저장하는 배열을 만들 수 있다. 우선 vector의 경우 생성자 인자로 숫자를 전달해주면 capacity가 정해진 배열을 만드는 등을 할 수 있었는데, TArray는 이러한 생성자가 없는 걸로 보인다. 대신 Init() 이라는 함수를 제공한다. 이 함수는 인자로 T 타입 Value, Count를 받는다. 그럼 Value를 Count개 만큼 생성하여 배열에 넣어준다.

[공간 예약]
동적 배열의 경우 원소를 더 이상 추가할 수 없으면 자동으로 capacity를 늘려주게 되는데, 이때 내부적으로 메모리를 새로 할당하고 기존 원소를 모두 복사하여 옮기게 된다. 그래서 이러한 부하를 줄이기 위해 보통 미리 사용할 크기를 알 경우 reserve() 함수를 통해 공간을 미리 예약 후 사용한다. TArray 클래스 또한 Reserve()란 이름으로 제공한다. 

[원소 추가]
배열의 끝에 원소를 추가하고 싶다면 push_back() 대신 Add() 혹은 Push() 함수를 사용하면 된다. 차이점은 인덱스를 반환하냐 안하냐 뿐이다. emplace()도 동일한 이름으로 제공한다.(첫 문자 대문자) 언리얼에선 Append()라는 함수를 제공하는데, 인자로 TArray를 전달하면 기존 배열의 뒤에 추가해준다. 몇개만 추가할 것인지 설정할 수도 있다.

[원소 삭제]
pop_back()은 Pop()이라는 함수로 제공한다. 맨 앞의 원소를 빼는 함수를 제공하는진 모르겠지만, 동적 배열에서 이러한 연산을 하면 원소를 한칸씩 모두 당겨야 되기 때문에 사용하지 않는 것이 좋다. 벡터를 비우고 싶을 땐 clear() 함수를 사용 했는데, 여기선 Empty()라는 이름으로 제공한다. 인자로 Slack을 받는데 아래에서 설명하겠지만, 배열을 비우고 capacity를 몇으로 유지할지 설정하는 것이라 생각하면 된다. 원래 vector에서 empty()는 배열이 비었는지 확인하는 함수였는데, 여기선 다르므로 헷갈리지 않게 조심해야 한다. TArray에선 그냥 배열의 크기가 0인지 비교하여 확인해야 하는 것 같다.

[탐색]
vector에서 원소를 선형 탐색하려면 begin()을 통해 반복자를 얻거나 range based for를 사용했다. TArray 또한 둘 다 지원한다. 다만 TArray의 begin() 함수를 보면 직접 사용하지 말라고 되어 있다. 대신 CreateIterator() 혹은 CreateConstIterator() 함수를 사용하는 듯 하다. 근데 end()를 직접 호출은 불가능한가보다. 범위 기반 for는 동일하게 사용 가능하다.

[Getter]
만약 배열의 시작 주소를 얻고 싶다면 GetData()를 사용하면 된다. 배열의 크기는 size() 대신 Num()을 사용한다. 배열의 capacity를 알고 싶다면 Max()를 사용한다. 그리고 슬랙(Slack)이라는 개념이 있는데 이건 capacity에서 현재 사용 중인 크기를 제외한 나머지 크기이다. 즉 Max()가 16이고 Num()이 4라면 GetSlack()은 12가 된다. 

[AddUninitialized()]
FMemory::Memcpy()를 사용하고 싶은 경우가 있다. 미리 할당된 메모리 공간에 데이터를 복사하는 것이므로 저장할 곳의 메모리가 할당되어 있어야 한다. 그럴 때 TArray를 만들고 AddUninitialized(n)를 호출하면 초기화 되지 않은 공간 n개를 만들어 준다. 어차피 데이터를 덮어 씌울 것이기 때문에 초기화하는 낭비를 줄여줄 수 있다.

일단 기본적인 것만 알아보고 필요한 건 그때 찾아보면 될 것 같다.




댓글