首页 > 编程语言 >UE5 C++ TMap

UE5 C++ TMap

时间:2023-06-22 19:58:39浏览次数:37  
标签:Kiwi TMap 映射 Value Melon C++ Key UE5 FruitMap

概述

  • 映射的元素类型为键值对,元素类型实际上是 TPair<KeyType, ElementType>,只将键用于存储和获取
  • TMapTMultiMap 两者之间的不同点是TMap中的键是唯一的,而TMultiMap可存储多个相同的键
  • TMap是散列容器,这意味着键类型必须支持GetTypeHash函数,并提供运算符==来比较各个键是否等值

创建

  TMap<int32, FString> FruitMap;

添加元素

  • Add 函数

    • 添加重复键,覆盖已有的
    • 可接受不带值的键,调用此重载后的 Add 时,值将被默认构建:
    FruitMap.Add(5, TEXT("Banana"));
        FruitMap.Add(2, TEXT("Grapefruit"));
        FruitMap.Add(7, TEXT("Pineapple"));
        // FruitMap == [
        //  { Key:5, Value:"Banana"     },
        //  { Key:2, Value:"Grapefruit" },
        //  { Key:7, Value:"Pineapple"  }
        // ]
    
     FruitMap.Add(2, TEXT("Pear"));
        // FruitMap == [
        //  { Key:5, Value:"Banana"    },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" }
        // ]
    FruitMap.Add(4);
        // FruitMap == [
        //  { Key:5, Value:"Banana"    },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:""          }
        // ]
    
  • Emplace代替Add,防止插入映射时创建临时文件

    FruitMap.Emplace(3, TEXT("Orange"));
        // FruitMap == [
        //  { Key:5, Value:"Banana"    },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:""          },
        //  { Key:3, Value:"Orange"    }
        // ]
    
  • Append 函数合并映射,将一个映射的所有元素移至另一个映射

     TMap<int32, FString> FruitMap2;
        FruitMap2.Emplace(4, TEXT("Kiwi"));
        FruitMap2.Emplace(9, TEXT("Melon"));
        FruitMap2.Emplace(5, TEXT("Mango"));
        FruitMap.Append(FruitMap2);
        // FruitMap == [
        //  { Key:5, Value:"Mango"     },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:"Kiwi"      },
        //  { Key:3, Value:"Orange"    },
        //  { Key:9, Value:"Melon"     }
        // ]
        // FruitMap2 is now empty.
    

迭代

  • 范围 for-range

     for (auto& Elem :FruitMap)
        {
            FPlatformMisc::LocalPrint(
                *FString::Printf(
                    TEXT("(%d, \"%s\")\n"),
                    Elem.Key,
                    *Elem.Value
                )
            );
        }
        // Output:
        // (5, "Mango")
        // (2, "Pear")
        // (7, "Pineapple")
        // (4, "Kiwi")
        // (3, "Orange")
        // (9, "Melon")
    
  • 迭代器

    • CreateIterator 返回拥有读写访问权限的迭代器
    • CreateConstIterator 返回拥有只读访问权限的迭代器
     for (auto It = FruitMap.CreateConstIterator(); It; ++It)
        {
            FPlatformMisc::LocalPrint(
                *FString::Printf(
                    TEXT("(%d, \"%s\")\n"),
                    It.Key(),   // same as It->Key
                    *It.Value() // same as *It->Value
                )
            );
        }
    

查询

  • Num函数查询map中保存的元素数量

     int32 Count = FruitMap.Num();     // Count == 6
    
  • Contains函数确定映射是否包含特定键

     bool bHas7 = FruitMap.Contains(7);   // bHas7 == true
     bool bHas8 = FruitMap.Contains(8);    // bHas8 == false
    
  • 运算符[]获取特定键对应的值

        FString Val7 = FruitMap[7];    // Val7 == "Pineapple"
        FString Val8 = FruitMap[8];   // Assert!
    
  • Find 返回指向特定键对应值的指针,如果map不包含该键,则返回nullptr

     FString* Ptr7 = FruitMap.Find(7);   // *Ptr7 == "Pineapple"
     FString* Ptr8 = FruitMap.Find(8);   //  Ptr8 == nullptr
    
  • FindOrAdd将返回对与给定键关联的值的引用

    • 如果映射中不存在该键,FindOrAdd 将返回新创建的元素(使用给定键和默认构建值),该元素也会被添加到映射
    • 仅适用于非常量映射
  • FindRef会返回与给定键对应值的副本

    • 若映射中未找到给定键,则返回默认构建值
    • 不会创建新元素,因此既可用于常量映射,也可用于非常量映射
    FString& Ref7 = FruitMap.FindOrAdd(7);
        // Ref7     == "Pineapple"
        // FruitMap == [
        //  { Key:5, Value:"Mango"     },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:"Kiwi"      },
        //  { Key:3, Value:"Orange"    },
        //  { Key:9, Value:"Melon"     }
        // ]
        FString& Ref8 = FruitMap.FindOrAdd(8);
        // Ref8     == ""
        // FruitMap == [
        //  { Key:5, Value:"Mango"     },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:"Kiwi"      },
        //  { Key:3, Value:"Orange"    },
        //  { Key:9, Value:"Melon"     },
        //  { Key:8, Value:""          }
        // ]
    
        FString Val7 = FruitMap.FindRef(7);
        FString Val6 = FruitMap.FindRef(6);
        // Val7     == "Pineapple"
        // Val6     == ""
        // FruitMap == [
        //  { Key:5, Value:"Mango"     },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:"Kiwi"      },
        //  { Key:3, Value:"Orange"    },
        //  { Key:9, Value:"Melon"     },
        //  { Key:8, Value:""          }
        // ]
    
  • FindKeyFind相对,其返回指向与所提供值配对的第一个键的指针,搜索映射中不存在的值将返回nullptr

    • 如果映射有多个具有相同值的键
    • FindKey 可返回其中任一键
    const int32* KeyMangoPtr   = FruitMap.FindKey(TEXT("Mango"));   // *KeyMangoPtr   == 5
    const int32* KeyKumquatPtr = FruitMap.FindKey(TEXT("Kumquat")); //  KeyKumquatPtr == nullptr 
    
  • GenerateKeyArray 使用所有键副本来填充 TArray

  • GenerateValueArray 使用所有值的副本来填充 TArray

  • 在这两种情况下,都会在填充前清空所传递的数组,因此产生的元素数量始终等于映射中的元素数量

     TArray<int32>   FruitKeys;
        TArray<FString> FruitValues;
        FruitKeys.Add(999);
        FruitKeys.Add(123);
        FruitMap.GenerateKeyArray  (FruitKeys);
        FruitMap.GenerateValueArray(FruitValues);
        // FruitKeys   == [ 5,2,7,4,3,9,8 ]
        // FruitValues == [ "Mango","Pear","Pineapple","Kiwi","Orange",
        //                  "Melon","" ]
    

移除元素

  • Remove 函数移除指定键的元素
    • 返回值是被移除元素的数量
    • 如果映射不包含与键匹配的元素,则返回值可为零
       FruitMap.Remove(8);
        // FruitMap == [
        //  { Key:5, Value:"Mango"     },
        //  { Key:2, Value:"Pear"      },
        //  { Key:7, Value:"Pineapple" },
        //  { Key:4, Value:"Kiwi"      },
        //  { Key:3, Value:"Orange"    },
        //  { Key:9, Value:"Melon"     }
        // ]
    
  • FindAndRemoveChecked函数可用于从map移除元素并返回其值
    • 若键不存在,映射将调用 check(UE4中等同于 assert)
     FString Removed7 = FruitMap.FindAndRemoveChecked(7);
        // Removed7 == "Pineapple"
        // FruitMap == [
        //  { Key:5, Value:"Mango"  },
        //  { Key:2, Value:"Pear"   },
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:3, Value:"Orange" },
        //  { Key:9, Value:"Melon"  }
        // ]
    
        FString Removed8 = FruitMap.FindAndRemoveChecked(8);
        // Assert!
    
  • RemoveAndCopyValue的作用 与 Remove 相似,不同点是会将已移除元素的值复制到引用参数
    • 如果映射中不存在指定的键,则输出参数将保持不变,函数将返回 false
    FString Removed;
        bool bFound2 = FruitMap.RemoveAndCopyValue(2, Removed);
        // bFound2  == true
        // Removed  == "Pear"
        // FruitMap == [
        //  { Key:5, Value:"Mango"  },
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:3, Value:"Orange" },
        //  { Key:9, Value:"Melon"  }
        // ]
        bool bFound8 = FruitMap.RemoveAndCopyValue(8, Removed);
        // bFound8  == false
        // Removed  == "Pear", i.e. unchanged
        // FruitMap == [
        //  { Key:5, Value:"Mango"  },
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:3, Value:"Orange" },
        //  { Key:9, Value:"Melon"  }
        // ]
    
  • EmptyReset 函数可将映射中的所有元素移除
    • Empty 可采用参数指示映射中保留的slack量
    • Reset 则是尽可能多地留出slack量
    TMap<int32, FString> FruitMapCopy = FruitMap;
        // FruitMapCopy == [
        //  { Key:5, Value:"Mango"  },
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:3, Value:"Orange" },
        //  { Key:9, Value:"Melon"  }
        // ]
    
        FruitMapCopy.Empty();       // We could also have called Reset() here.
        // FruitMapCopy == []
    

排序

  • KeySortValueSort 函数可分别按键和值进行排序,两个函数均使用二元谓词来进行排序
     FruitMap.KeySort([](int32 A, int32 B) {
            return A > B; // sort keys in reverse
        });
        // FruitMap == [
        //  { Key:9, Value:"Melon"  },
        //  { Key:5, Value:"Mango"  },
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:3, Value:"Orange" }
        // ]
    
     FruitMap.ValueSort([](const FString& A, const FString& B) {
            return A.Len() < B.Len(); // sort strings by length
        });
        // FruitMap == [
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:5, Value:"Mango"  },
        //  { Key:9, Value:"Melon"  },
        //  { Key:3, Value:"Orange" }
        // ]
    

运算符

  • 通过标准复制构造函数或赋值运算符进行复制,因为映射严格拥有其元素,复制映射的操作是深层的,所以新的映射将拥有其自己的元素副本
     TMap<int32, FString> NewMap = FruitMap;
        NewMap[5] = "Apple";
        NewMap.Remove(3);
        // FruitMap == [
        //  { Key:4, Value:"Kiwi"   },
        //  { Key:5, Value:"Mango"  },
        //  { Key:9, Value:"Melon"  },
        //  { Key:3, Value:"Orange" }
        // ]
        // NewMap == [
        //  { Key:4, Value:"Kiwi"  },
        //  { Key:5, Value:"Apple" },
        //  { Key:9, Value:"Melon" }
        // ]
    
  • MoveTemp函数可调用移动语义
  FruitMap = MoveTemp(NewMap);
    // FruitMap == [
    //  { Key:4, Value:"Kiwi"  },
    //  { Key:5, Value:"Apple" },
    //  { Key:9, Value:"Melon" }
    // ]
    // NewMap == []

Slack

  • Slack是不包含元素的已分配内存
  • Reserve可分配内存,无需添加元素
  • 通过非零slack参数调用 ResetEmpty 可移除元素,无需将其使用的内存取消分配
  • Slack优化了将新元素添加到映射的过程,因为可以使用预先分配的内存,而不必分配新内存
  • 它在移除元素时也十分实用,因为系统不需要将内存取消分配
  • 在清空希望用相同或更少的元素立即重新填充的映射时,此方法尤其有效
     FruitMap.Reserve(10);
        for (int32 i = 0; i < 10; ++i)
        {
            FruitMap.Add(i, FString::Printf(TEXT("Fruit%d"), i));
        }
        // FruitMap == [
        //  { Key:9, Value:"Fruit9" },
        //  { Key:8, Value:"Fruit8" },
        //  ...
        //  { Key:1, Value:"Fruit1" },
        //  { Key:0, Value:"Fruit0" }
        // ]
    
  • 使用 CollapseShrink 函数可移除 TMap 中的全部slack
    • Shrink 将从容器的末端移除所有slack,但这会在中间或开始处留下空白元素
     for (int32 i = 0; i < 10; i += 2)
        {
            FruitMap.Remove(i);
        }
        // FruitMap == [
        //  { Key:9, Value:"Fruit9" },
        //  <invalid>,
        //  { Key:7, Value:"Fruit7" },
        //  <invalid>,
        //  { Key:5, Value:"Fruit5" },
        //  <invalid>,
        //  { Key:3, Value:"Fruit3" },
        //  <invalid>,
        //  { Key:1, Value:"Fruit1" },
        //  <invalid>
        // ]
        FruitMap.Shrink();
        // FruitMap == [
        //  { Key:9, Value:"Fruit9" },
        //  <invalid>,
        //  { Key:7, Value:"Fruit7" },
        //  <invalid>,
        //  { Key:5, Value:"Fruit5" },
        //  <invalid>,
        //  { Key:3, Value:"Fruit3" },
        //  <invalid>,
        //  { Key:1, Value:"Fruit1" }
        // ]
    
    • 在上述代码中,Shrink 只删除了一个无效元素,因为末端只有一个空元素
    • 要移除所有slack,首先应调用 Compact 函数,将空白空间组合在一起,为调用 Shrink 做好准备
    FruitMap.Compact();
        // FruitMap == [
        //  { Key:9, Value:"Fruit9" },
        //  { Key:7, Value:"Fruit7" },
        //  { Key:5, Value:"Fruit5" },
        //  { Key:3, Value:"Fruit3" },
        //  { Key:1, Value:"Fruit1" },
        //  <invalid>,
        //  <invalid>,
        //  <invalid>,
        //  <invalid>
        // ]
        FruitMap.Shrink();
        // FruitMap == [
        //  { Key:9, Value:"Fruit9" },
        //  { Key:7, Value:"Fruit7" },
        //  { Key:5, Value:"Fruit5" },
        //  { Key:3, Value:"Fruit3" },
        //  { Key:1, Value:"Fruit1" }
        // ]
    

标签:Kiwi,TMap,映射,Value,Melon,C++,Key,UE5,FruitMap
From: https://www.cnblogs.com/scyrc/p/17498104.html

相关文章

  • C++入门教程
    C++入门教程----------------------------------------------------------一.初识C++---------------------------------------------------------1.什么是C++.c++是一种较为基础的编程语言,虽然没有Python,Scratch那么高级,但是它应用范围很广.不论是信息奥赛还是国......
  • UE5 C++ TArray
    概述TArray是UE4中最常用的容器类。其速度快、内存消耗小、安全性高TArray类型由两大属性定义:元素类型和可选分配器元素类型是存储在数组中的对象类型。TArray被称为同质容器。换言之,其所有元素均完全为相同类型。单个TArray中不能存储不同类型的元素。分配器常被省略,默......
  • c++ doctest 测试报告
    地址https://github.com/laolang2016/doctest-reports效果未完成事项状态筛选没做只做了dashboard,其他两个页面还是空白四栏确实有点多了,数据应该纵向展示jquery果然还是比较墨迹,下一个版本使用vue......
  • Delete vector contents and free up memory in C++
     DeletevectorcontentsandfreeupmemoryinC++Thispostwilldiscusshowtodeletethevector’scontentsandfreeupthememoryallocatedbythevectortostoreobjectsinC++.1.Using vector::clear functionWecanusethe vector::clear......
  • visual studio 2022 c++ doxygen风格注释
    设置工具/选项/文本编辑器/C/C++/代码样式/常规注释效果输入/**添加注释鼠标停靠注释预览......
  • C++面试八股文:用过STL吗?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第21面:面试官:用过STL吗?二师兄:(每天都用好吗。。)用过一些。面试官:你知道STL是什么?二师兄:STL是指标准模板库(StandardTemplateLibrary),是C++区别于C语言的特征之一。面试官:那你知道STL的六大部件是什么?二师兄:分别是容器(container......
  • C++面试八股文:了解auto关键字吗?
    C++面试八股文:了解auto关键字吗?某日二师兄参加XXX科技公司的C++工程师开发岗位第15面:面试官:了解auto关键字吗?二师兄:嗯,了解一些(我很熟悉)。面试官:说一说auto的用法吧?二师兄:auto主要是为了编译器进行类型推导。比如:autoi=42; //i被推导位int型std::vector<int>vi......
  • 现代C++学习指南-具体类
    类作为C++中重要的概念之一,有着众多的特性,也是最迷人的部分!类是一个加工厂,开发者使用C++提供的各种材料组装这个工厂,使得它可以生产出符合自己要求的数据,通过对工厂的改造,可以精细控制对象从出生到死亡的各种行为,真正达到我的代码我做主的境界。类我们经常说的面向对象三大特......
  • stringstream 与auto c++
    stringstream的用法,动态创建不同文件名for(inti=0;i<n;i++) { stringfilename; stringstreamss; ss<<"file"<<i<<".txt"; ss>>filename; ss.clear(); }auto的用法,通常用于for循环常规思路,我们想要输出一个数组的全部元素时,往往采用以下......
  • C++中的类简要介绍
    (文章目录)前言本篇文章讲给大家介绍一个C++中重要的概念,了解了这个概念大家就明白了为什么C++会叫做面向对象编程了。一、什么是类什么是对象1.类的概述其实我们生活中有很多类的例子,就像老虎是猫科动物可以看作一个大类,昆虫又是一个大类,机动车和非机动车又是不同的类。通过......