Using TMap in C++ within Unreal Engine for Key-Value Pair Storage

Using TMap in C++ within Unreal Engine for Key-Value Pair Storage

In C++ within Unreal Engine, TMap is an associative container used for storing key-value pairs, similar to the standard library’s std::map, but optimized for UE’s memory management and performance. Below are the basic usage and common operation examples of TMap:

1. Include Header File

To use TMap, you need to include its header file:

#include "Containers/Map.h"

2. Declaration

The template parameters for TMap are Key Type and Value Type, and the declaration is as follows:

// Declare a TMap with int as key and FString as valueTMap<int32, FString> IntToStringMap;// Declare a TMap with FName as key and AActor* as value (storing Actor references)TMap<FName, AActor*> NameToActorMap;// Declare nested types (e.g., the value of TMap can be another container)TMap<FString, TArray<int32>> StringToIntArrayMap;

3. Basic Operation Examples

// Include necessary header files#include "Containers/Map.h"#include "CoreMinimal.h"#include "GameFramework/Actor.h"
void TMapExample() {
    // 1. Declare and initialize TMap (Key: Player ID, Value: Player Name)
    TMap<int32, FString> PlayerMap;
    // 2. Insert elements (three methods)
    // Method 1: Use Add(), which overwrites the old value if the key already exists
    PlayerMap.Add(1, TEXT("PlayerOne"));
    PlayerMap.Add(2, TEXT("PlayerTwo"));
    // Method 2: Use Emplace() (more efficient, constructs the object directly in the container)
    PlayerMap.Emplace(3, TEXT("PlayerThree"));
    // Method 3: Use [] operator (inserts if the key does not exist, modifies if it does)
    PlayerMap[4] = TEXT("PlayerFour");

    // 3. Find elements
    // Method 1: Use Find(), returns a pointer to the value (returns nullptr if not found)
    if (const FString* FoundPlayer = PlayerMap.Find(2)) {
        UE_LOG(LogTemp, Log, TEXT("Found Player 2: %s"), **FoundPlayer);
    }
    // Method 2: Use FindOrAdd(), inserts a default value if not found and returns a reference
    FString& Player5 = PlayerMap.FindOrAdd(5, TEXT("DefaultPlayer")); // Insert key 5
    Player5 = TEXT("PlayerFive"); // Modify value
    // Method 3: Use Contains() to check if the key exists
    if (PlayerMap.Contains(3)) {
        UE_LOG(LogTemp, Log, TEXT("Player 3 exists"));
    }

    // 4. Iterate TMap
    // Method 1: Use iterator (iterate key-value pairs)
    for (const auto& Pair : PlayerMap) {
        int32 PlayerId = Pair.Key;
        const FString& PlayerName = Pair.Value;
        UE_LOG(LogTemp, Log, TEXT("ID: %d, Name: %s"), PlayerId, *PlayerName);
    }
    // Method 2: Iterate only keys
    for (const int32& Key : PlayerMap.GetKeys()) {
        UE_LOG(LogTemp, Log, TEXT("Key: %d"), Key);
    }

    // 5. Modify elements
    if (FString* MutablePlayer = PlayerMap.Find(1)) {
        *MutablePlayer = TEXT("PlayerOneModified"); // Modify value via pointer
    }

    // 6. Remove elements
    // Method 1: Remove by key, returns whether removal was successful
    bool bRemoved = PlayerMap.Remove(4);
    if (bRemoved) {
        UE_LOG(LogTemp, Log, TEXT("Successfully removed Player 4"));
    }
    // Method 2: Clear all elements
    // PlayerMap.Empty();

    // 7. Other common methods
    int32 MapSize = PlayerMap.Num(); // Get number of elements
    UE_LOG(LogTemp, Log, TEXT("Current map size: %d"), MapSize);
    bool bIsEmpty = PlayerMap.IsEmpty(); // Check if empty
}
// Advanced example: Storing Actor pointers and accessing safely
void ActorMapExample() {
    TMap<FName, AActor*> ActorMap;
    // Assume some Actors already exist
    AActor* ActorA = GetSomeActor(); // Custom function to get an Actor
    AActor* ActorB = GetAnotherActor();
    // Insert Actors (key is the name of the Actor)
    ActorMap.Add(ActorA->GetFName(), ActorA);
    ActorMap.Add(ActorB->GetFName(), ActorB);
    // Find and safely access Actor (check pointer validity)
    FName TargetName = TEXT("MyActor");
    if (AActor** FoundActor = ActorMap.Find(TargetName)) {
        // Double-check if Actor is valid (avoid accessing destroyed Actor)
        if (IsValid(*FoundActor) && !(*FoundActor)->IsPendingKillPending()) {
            (*FoundActor)->SetActorLabel(TEXT("FoundActor"));
        } else {
            // Clean up invalid Actor reference
            ActorMap.Remove(TargetName);
        }
    }
}

Leave a Comment