[STL vector의 push_back()과 emplace_back()의 차이점]
push_back()과 emplace_back() 모두 stl vector의 요소 끝에 원소를 추가하는 함수입니다.
다만, push_back()은 이미 생성된 객체를 복사 혹은 이동을 통해 추가하고
emplace_back()은 필요한 인자를 직접 파라미터로 받아 벡터 내부에서 직접 객체를 생성합니다.
push_back()은 동작 과정 중 임시 객체를 생성하여 복사 혹은 이동을 수행하므로 emplace_back()에 비해서
오버헤드가 발생합니다.
추가적으로 컴파일러에 따라 혹은 emplace_back()을 사용하는 것이 push_back()에 비해 효율적이지 않은 경우에도
push_back()과 동일한 성능을 가집니다.
효율적이지 않은 경우는 다음과 같습니다.
1. 이미 생성된 객체를 emplace_back()으로 전달하는 경우, 복사가 발생합니다.
2. 벡터가 참조를 저장하는 컨테이너가 아닌 경우 원본 객체가 아닌 복사본이 저장됩니다.
3. 암시적 변환이 필요한 경우 변환에 필요한 임시 객체 생성이 발생합니다.
4. 템플릿 타입 추론이 실패하거나 reference collapsing이 예상대로 작동하지 않는 특정 상황
5. 벡터의 용량이 부족해 재할당이 발생하는 경우
6. 복사 생성자, 이동 생성자가 emplace_back()에 전달된 매개변수와 일치하는 경우
7. 생성자가 lvalue를 받는 경우
8. RVO(Return Value Optimization)가 적용되지 않는 경우
[TArray와 STL Vector의 차이점]
TArray의 경우 vector와 동일한 동적 배열 자료구조입니다. 그러나 TArray에는 언리얼 엔진에서 사용될 것을 고려하여 제작되었습니다.
따라서 UPROPERTY 지원과 네트워크 리플리케이션, 시리얼라이제이션 등이 제공됩니다. 추가적으로 vector에 비해서 작은 비용으로
배열 크기의 확장이 일어나게 됩니다. 조정 중 복사, 이동, 소멸자 등을 호출하지 않기 때문입니다.
그리고 vector와 다르게 자체적인 Sort, HeapSort, StableSort 함수를 통한 정렬 제공과 Heapify 함수를 통해 배열을 힙 자료구조 형태로 변환할 수 있습니다.
[CDO]
CDO는 클래스 디폴트 오브젝트의 약자로 주요 기능은 클래스 객체의 기본 상태를 저장하고 기본 변수 상태를 유지하는 것입니다.
UCLASS 매크로가 붙어 생성되는 UClass들은 각각의 CDO를 엔진 실행 초기 단계에서 생성하게 됩니다.
CDO를 언리얼 엔진에서 활용하는 방식은 다음과 같습니다.
1. 클래스를 인스턴스화 할 때, CDO의 값을 복사해서 초기화
2. 블루프린트 혹은 C++에서 설정한 기본값이 CDO에 저장됩니다.
3. 네트워크 리플리케이션 시 CDO와 다른 변경된 값만을 전송합니다.
4. 직렬화, 역직렬화 시 CDO와 다른 값만을 저장합니다.
[PlayerState]
언리얼 엔진에서 플레이어의 상태 정보를 저장하고 관리합니다.
네트워크를 활용한 게임인 경우 플레이어 별 정보를 추적, 동기화하는데 필수적인 역할을 합니다.
각 플레이어마다 하나씩 존재하며, APlayerState 클래스에서 파생됩니다.
플레이어가 접속해 있는 동안 존재하며 레벨 전환 시에도 기본적으로 유지됩니다.
플레이어가 재접속해도 동일한 PlayerState가 재사용될 수 있으며
서버에서 생성되고 관리됩니다. 클라이언트에서는 리플리케이션이 됩니다.
주요 기능을 설명드리면
플레이어의 식별에 필요한 이름, 고유 ID, 팀 정보가 있으며
게임 통계에 필요한 점수, 네트워크 동기화와 관련된 변수, 기능들이 포함되어 있습니다.
[unordered와 ordered 자료구조의 차이]
1. ordered 컨테이너의 경우 일반적으로 Red-black tree로 구현되어 균형 이진 검색 트리의 형태를 뜁니다. 이로 인해 요소들이 키를 기준으로 정렬된 상태를 유지합니다.
시간 복잡도는 검색/삽입/삭제의 경우 O(log n), 순회는 O(n)입니다.
이로 인해서 범위 검색에 효율적이고 반복 순회시에는 정렬된 순서로 접근할 수 있다는 특징이 있습니다.
2. unordered 컨테이너의 경우 해시 테이블로 구현되어 해시 함수를 사용해 버킷에 요소가 할당됩니다. 충돌 해결을 위해 체이닝 방식을 사용합니다.
시간 복잡도는 평균적으로는 검색, 삽입, 삭제의 경우 O(1), 충돌이 많은 경우로 발생하는 최악의 경우는 O(n)이 됩니다.
주요한 특징으로는 이름과 동일하게 정렬되지 않은 상태로 저장되고 빠른 검색 속도, 범위 검색 불가, 순회 순서의 예측 불가능이 있습니다.
[액터의 EndPlay와 Destroyed의 차이점]
Destroyed의 경우 Destroy() 호출을 통해 액터가 파괴될 때에만 호출되나, EndPlay의 경우 액터가 월드에서 제거될 때, 레벨 전환 시, 게임 종료 시, 가비지 컬렉션으로 인한 제거, Destroy 호출 시 등
다양한 이유로 호출된다는 차이가 존재합니다.
Destroyed와는 다르게 EndPlay에서는 종료 이유에 대한 파라미터가 입력 인자로 들어오기에 이에 따라 각각의 이유에 대한 분기 처리가 가능하다는 점이 있습니다.
[언리얼에서 게임이 시작될 때 어떤 객체들이 어떤 순서로 생성되는지 간략하게 설명해주세요.]
Engine 초기화 -> GameInstance 생성 -> World 생성 -> GameMode 생성 -> GameState 생성 -> Level 에 배치된 모든 액터 스폰 및 초기화 함수(PostLoad, PostActorCreated) 호출
PlayerController 생성 -> PlayerState 생성 -> Default Pawn / Character 생성 및 빙의 -> HUD 생성
[언리얼 엔진의 가비지 컬렉션 시스템이 어떻게 동작하는지 설명]
언리얼 엔진의 GC는 표준 Mark&Sweep 컬렉터입니다.
Mark unreachable, Mark Rechable, Sweep, Shrink Hash Table의 네 단계로 동작합니다.
Maek unreachable에서는 메모리 상 존재하는 모든 오브젝트를 스캔하여 root set에서 시작하여 해당 오브젝트까지 도달할 수 없는 모든 오브젝트를 식별하고
Mark rechable에서는 루트 세트에서 도달 가능한 모든 오브젝트를 찾아냅니다.
Sweep 단게에서는 메모리 전체를 스캔하면서 Mark unreachable로 세팅된 오브젝트의 메모리를 해제합니다.
shrink hash table 단계에서는 가비지 컬렉션 과정에서 사용된 해시 테이블의 크기를 줄입니다.
[GameInstance는 어떤 역할을 하며, 언제 사용해야 하는지 설명해 주세요.]
게임이 실행되는 동안 단일 인스턴스로 유지되는 객체로, 게임의 생명주기 동안 지속적으로 존재합니다. 주요 역할은 다음과 같습니다:
게임 전역 데이터 관리
게임 초기화 및 종료 처리
네트워크 세션 관리
월드와 독립적인 로직 처리
레벨 간 데이터 유지 필요 시
게임 전역 설정 관리
싱글톤 패턴 대체
네트워크 관련 작업
게임 시작/종료 시 커스텀 로직 필요 시
[erase와 remove의 차이]
erase는 실제 데이터를 지워 capacity가 감소되는 효과가 있으나 remove의 경우 삭제할 값이 위치한 곳으로부터 뒤의 값들이 앞으로 한 칸씩 이동하여 덮어씌워지게 됩니다.
이 때 remove의 경우 삭제된 원소가 있는 컨테이너의 마지막 위치를 반환하는데, 이를 이용하여 erase와 함께 사용하여 erase(remove에서 반환된 위치, vector.end())를 사용하여 사용하지 않게 된 마지막 위치를
벡터에서 제거할 수 있게 됩니다.
[언리얼에서 object의 메모리 관리]
언리얼 엔진에서 메모리 관리가 자동으로 이루어지는 객체는 UObject 클래스와 그 파생 클래스들(AActor, UActorComponent 등)입니다.
가비지 컬렉션의 역할: GC는 더 이상 참조되지 않는 UObject를 주기적으로 탐지하고 메모리에서 해제합니다. 이를 통해 메모리 누수(Memory Leak)를 방지합니다.
[액터의 생명 주기]
생성: SpawnActor() → 생성자 → PostActorCreated().
초기화: PostInitializeComponents() → BeginPlay().
활동: Tick() 및 이벤트 처리.
종료 준비: EndPlay() → Destroyed().
파괴: Destroy() → GC에 의해 메모리 해제.
'TIL(Today I Learned)' 카테고리의 다른 글
| 250327 TIL - 면접 대비(Override & Overload) (0) | 2025.03.27 |
|---|---|
| 250324 TIL - 모의면접 (0) | 2025.03.24 |
| 250319 TIL - SourceInsight 사용기 (0) | 2025.03.19 |
| 250312 TIL - 언리얼 엔진 빌드 후기 (0) | 2025.03.12 |
| 250307 TIL - The Fourth Descendant 프로젝트 완료 및 KPT 회고 (0) | 2025.03.07 |