일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- MLFQ
- STCF
- AINCAA
- dtft
- 운영체제
- CTF
- Double free
- dirty cow
- 메카님
- RBAC
- TSet
- 유니티
- linear difference equation
- Security
- 게임개발
- frequency-domain spectrum analysis
- Unity #Indie Game
- DP
- pdlc
- MAC
- Race condition
- 유스케이스
- DSP
- sampling theory
- 언리얼엔진
- 배경 그림
- Rr
- stride
- 게임 개발
- ret2libc
- Today
- Total
다양한 기록
[UE] Unreal Container Library / Struct, Map 본문
구조체
USTRUCT 매크로 추가하고 (내부에 BlueprintType같은 키워드 추가 가능)
내부 상단에 GENERATED_BODY() 추가 (안해도 되긴 하는데 해야 리플렉션, 직렬화 가능)
내무 멤버 변수는 UPROPERTY() 매크로 사용
* 언리얼 오브젝트가 아니니 F로 시작
사용 용도가 언리얼 오브젝트와는 완전히 다름
단순한 데이터 타입에 적합함
F로 시작하니까 일반 객체 -> 리플렉션 시스템이 인식 못함
대신 내부의 UPROPERTY로 선언된 변수들은 인식함
UFUNCTION()은 안됨
대부분 힙 할당 없이 스택 내 데이터로 사용,
NewObject()도 지원 안됨
하나의 멤버를 UFiled 클래스가 관리
UScriptStruct가 GENERATED_BODY가 들어간 구조체
UFinction은 UClass는 가져도 다른 애들은 안가짐
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"
USTRUCT()
struct FStudentData
{
GENERATED_BODY()
FStudentData()
{
Name = TEXT("홍길동");
Order = -1;
}
FStudentData(const FString& InName, const int32& InOrder) : Name(InName), Order(InOrder) {}
UPROPERTY()
FString Name;
UPROPERTY()
int32 Order;
};
/**
*
*/
UCLASS()
class UNREALCONTAINER_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
virtual void Init() override;
private:
TArray<FStudentData> StudentsData;
UPROPERTY() // 내부적으로 포인터를 가져서 메모리 관리를 위해 필수
TArray<TObjectPtr<class UStudent>> Students;
};
FStudentData로 TArray를 선언 시 -> UPROPERTY 안해줘도 됨
UStudent로 선언 시 -> 해줘야 됨
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameInstance.h"
#include "Algo/Accumulate.h"
FString MakeRandomName()
{
TCHAR FirstChar[] = TEXT("김이박최");
TCHAR MiddleChar[] = TEXT("상혜지성");
TCHAR LastChar[] = TEXT("수은원연");
TArray<TCHAR> RandArray;
RandArray.SetNum(3);
RandArray[0] = FirstChar[FMath::RandRange(0, 3)];
RandArray[1] = MiddleChar[FMath::RandRange(0, 3)];
RandArray[2] = LastChar[FMath::RandRange(0, 3)];
return RandArray.GetData();
}
void UMyGameInstance::Init()
{
Super::Init();
const int32 ArrayNum = 10;
TArray<int32> Int32Array;
for (int32 ix = 1; ix <= ArrayNum; ++ix)
{
Int32Array.Add(ix);
}
Int32Array.RemoveAll(
[](int32 Val)
{
return Val % 2 == 0;
}
);
Int32Array += { 2, 4, 6, 8, 10 };
TArray<int32> Int32ArrayCompare;
int32 CArray[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
Int32ArrayCompare.AddUninitialized(ArrayNum);
FMemory::Memcpy(Int32ArrayCompare.GetData(), CArray, ArrayNum * sizeof(int32));
ensure(Int32Array == Int32ArrayCompare);
int32 Sum = 0;
for (const auto& num : Int32Array)
{
Sum += num;
}
int32 SumByAlgo = Algo::Accumulate(Int32Array, 0);
ensure(Sum == SumByAlgo);
////////////////////////////////////////////////////////////
TSet<int32> Int32Set;
for (int32 ix = 1; ix <= ArrayNum; ++ix)
{
Int32Set.Add(ix);
}
Int32Set.Remove(2);
Int32Set.Remove(4);
Int32Set.Remove(6);
Int32Set.Remove(8);
Int32Set.Remove(10);
Int32Set.Add(2);
Int32Set.Add(4);
Int32Set.Add(6);
Int32Set.Add(8);
Int32Set.Add(10);
const int32 StudentNum = 300;
for (int i = 0; i < StudentNum; ++i)
{
StudentsData.Emplace(FStudentData(MakeRandomName(), i));
}
TArray<FString> AllStudentsNames;
Algo::Transform(StudentsData, AllStudentsNames,
[](const FStudentData& Val)
{
return Val.Name;
}
);
UE_LOG(LogTemp, Log, TEXT("모든 학생 이름의 수: %d"), AllStudentsNames.Num());
TSet<FString> AllUniqueNames;
Algo::Transform(StudentsData, AllUniqueNames,
[](const FStudentData& Val)
{
return Val.Name;
}
);
UE_LOG(LogTemp, Log, TEXT("중복없는 학생 이름의 수: %d"), AllUniqueNames.Num());
}
이름과 순서를 구조체에 담아 TArray에 저장
Transform으로 컨테이너 변경 가능, 이때 람다 함수 사용
실행 잘 됨
TMap
STL map과 TMap의 차이
STL map
- 이진 트리로 구성, 메모리 구성 비효율적, 데이터 삭제 시 재구축 가능
- 순회에 적합하진 않음
TMap
- 키, 밸류 구성 튜플 TSet 구조
- 해시 테이블이라 빠른 검색, 동적 배열 등 TSet과 거의 유사한 구조
- TMultiMap 사용 시 중복 데이터(키 기준)를 관리 가능
TMap
내부적으로 엘리먼트는 TPair<KeyType, ElementType>으로 구성
키 유형은 GetTypeHash를 지원해야 하고, == 제공해야 함
TMap<int32, FString> FruitMap
이런 식으로 선언 가능
TSet과 사용법 거의 동일
KeyFuncs
커스텀 데이터 자료구조로 만드려면 해시값이 무엇인지 정의 필요
== 이랑 GetTypeHash 선언 필요
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"
USTRUCT()
struct FStudentData
{
GENERATED_BODY()
FStudentData()
{
Name = TEXT("홍길동");
Order = -1;
}
FStudentData(const FString& InName, const int32& InOrder) : Name(InName), Order(InOrder) {}
bool operator==(const FStudentData& InOther) const
{
return Order == InOther.Order;
}
friend FORCEINLINE uint32 GetTypeHash(const FStudentData& InStudentData)
{
return GetTypeHash(InStudentData.Order);
}
UPROPERTY()
FString Name;
UPROPERTY()
int32 Order;
};
/**
*
*/
UCLASS()
class UNREALCONTAINER_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
virtual void Init() override;
private:
TArray<FStudentData> StudentsData;
UPROPERTY() // 내부적으로 포인터를 가져서 메모리 관리를 위해 필수
TArray<TObjectPtr<class UStudent>> Students;
// 안에 언리얼 오브젝트나 포인터가 들어가진 않아 UPROPERTY 필수는 아님
TMap<int32, FString> StudentsMap;
};
FStudentData를 Set에 집어 넣으려고 하면 위에 보이는 것처럼
==이랑 GetTypeHash 선언 필요
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameInstance.h"
#include "Algo/Accumulate.h"
FString MakeRandomName()
{
TCHAR FirstChar[] = TEXT("김이박최");
TCHAR MiddleChar[] = TEXT("상혜지성");
TCHAR LastChar[] = TEXT("수은원연");
TArray<TCHAR> RandArray;
RandArray.SetNum(3);
RandArray[0] = FirstChar[FMath::RandRange(0, 3)];
RandArray[1] = MiddleChar[FMath::RandRange(0, 3)];
RandArray[2] = LastChar[FMath::RandRange(0, 3)];
return RandArray.GetData();
}
void UMyGameInstance::Init()
{
Super::Init();
const int32 ArrayNum = 10;
TArray<int32> Int32Array;
for (int32 ix = 1; ix <= ArrayNum; ++ix)
{
Int32Array.Add(ix);
}
Int32Array.RemoveAll(
[](int32 Val)
{
return Val % 2 == 0;
}
);
Int32Array += { 2, 4, 6, 8, 10 };
TArray<int32> Int32ArrayCompare;
int32 CArray[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
Int32ArrayCompare.AddUninitialized(ArrayNum);
FMemory::Memcpy(Int32ArrayCompare.GetData(), CArray, ArrayNum * sizeof(int32));
ensure(Int32Array == Int32ArrayCompare);
int32 Sum = 0;
for (const auto& num : Int32Array)
{
Sum += num;
}
int32 SumByAlgo = Algo::Accumulate(Int32Array, 0);
ensure(Sum == SumByAlgo);
////////////////////////////////////////////////////////////
TSet<int32> Int32Set;
for (int32 ix = 1; ix <= ArrayNum; ++ix)
{
Int32Set.Add(ix);
}
Int32Set.Remove(2);
Int32Set.Remove(4);
Int32Set.Remove(6);
Int32Set.Remove(8);
Int32Set.Remove(10);
Int32Set.Add(2);
Int32Set.Add(4);
Int32Set.Add(6);
Int32Set.Add(8);
Int32Set.Add(10);
const int32 StudentNum = 300;
for (int i = 0; i < StudentNum; ++i)
{
StudentsData.Emplace(FStudentData(MakeRandomName(), i));
}
TArray<FString> AllStudentsNames;
Algo::Transform(StudentsData, AllStudentsNames,
[](const FStudentData& Val)
{
return Val.Name;
}
);
UE_LOG(LogTemp, Log, TEXT("모든 학생 이름의 수: %d"), AllStudentsNames.Num());
TSet<FString> AllUniqueNames;
Algo::Transform(StudentsData, AllUniqueNames,
[](const FStudentData& Val)
{
return Val.Name;
}
);
UE_LOG(LogTemp, Log, TEXT("중복없는 학생 이름의 수: %d"), AllUniqueNames.Num());
Algo::Transform(StudentsData, StudentsMap,
[](const FStudentData& Val)
{
return TPair<int32, FString>(Val.Order, Val.Name);
}
);
UE_LOG(LogTemp, Log, TEXT("순번에 따른 학생 맵의 레코드 수: %d"), StudentsMap.Num());
TMap<FString, int32> StudentsMapByUniqueName;
Algo::Transform(StudentsData, StudentsMapByUniqueName,
[](const FStudentData& Val)
{
return TPair<FString, int32>(Val.Name, Val.Order);
}
);
UE_LOG(LogTemp, Log, TEXT("이름에 따른 학생 맵의 레코드 수: %d"), StudentsMapByUniqueName.Num());
TMultiMap<FString, int32> StudentsMapByName;
Algo::Transform(StudentsData, StudentsMapByName,
[](const FStudentData& Val)
{
return TPair<FString, int32>(Val.Name, Val.Order);
}
);
UE_LOG(LogTemp, Log, TEXT("이름에 따른 학생 멀티 맵의 레코드 수: %d"), StudentsMapByUniqueName.Num());
const FString TargetName = TEXT("이혜은");
TArray<int32> AllOrders;
StudentsMapByName.MultiFind(TargetName, AllOrders);
UE_LOG(LogTemp, Log, TEXT("이름에 %s인 학생 수: %d"), *TargetName, AllOrders.Num());
TSet<FStudentData> StudentsSet;
for (int32 ix = 1; ix <= ArrayNum; ++ix)
{
StudentsSet.Emplace( FStudentData(MakeRandomName(), ix) );
}
}
사용법은 다 비슷함
'언리얼 엔진 > Unreal C++' 카테고리의 다른 글
[UE] Serialization (직렬화) (0) | 2024.12.30 |
---|---|
[UE] Memory Management (0) | 2024.12.29 |
[UE] Unreal Container Library / TArray, TSet (0) | 2024.12.28 |
[UE] Delegate (델리게이트) / 발행 구독 패턴 (0) | 2024.12.26 |
[UE] Composition (컴포지션) (0) | 2024.12.22 |