从 C++ 基础到掌握 — 第 10 集
选择STL容器和可选
该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。
游戏中有不同类型的数据,例如队伍列表、怪物搜索、生成队列和击杀记录。 所有数据都可以用单个向量解析,但如果您使用适合目的的数据结构,代码会更清晰。
vector
std::vector是一个使用连续内存的动态数组。
std::vector<int> damages;
damages.reserve(10);
damages.push_back(10);
damages.emplace_back(20);
for (int damage : damages)
{
std::cout << damage << '\n';
}
该元素是[]或者at()方法。 at()检查范围,但是[]没有检查。
如果向量的容量不足,则会通过创建新的更大内存并移动现有元素来进行重新分配。 此时,指向现有元素的指针、引用和迭代器可能会失效。
unordered_map
要按项目 ID 快速查找项目,请使用哈希表。std::unordered_map这很适合你。
std::unordered_map<int, Item> itemDatabase;
itemDatabase.emplace(1, Item{1, "Sword", 100});
auto iter = itemDatabase.find(1);
if (iter != itemDatabase.end())
{
std::cout << iter->second.name << '\n';
}
find()如果失败end()返回。 在没有检查是否找到迭代器的情况下,不应取消引用迭代器。
队列和堆栈
队列是一种 FIFO 结构,先进入的值先出现。非常适合用作生成队列。
if (!spawnQueue.empty())
{
auto monster = spawnQueue.front();
spawnQueue.pop();
}
堆栈是一个 LIFO 结构,其中最后一个值首先出现。它可用于记录或撤销最近的击杀。
if (!killHistory.empty())
{
int lastMonsterId = killHistory.top();
killHistory.pop();
}
pop 不返回值。您必须首先使用 front 或 top 获取值,然后调用 pop。
optional
如果可能没有搜索结果,而不是一个特殊的错误值std::optional可以使用。
std::optional<Item> FindItem(int id) const
{
auto iter = itemDatabase.find(id);
if (iter == itemDatabase.end())
{
return std::nullopt;
}
return iter->second;
}
if (auto item = FindItem(1))
{
std::cout << item->name << '\n';
}
返回类型表明可能有也可能没有值。 盲目回答空选项value()你不应该打电话。您必须首先检查是否存在。
选择数据结构的标准不是时尚,而是预期用途。 有序列表可以表示为向量,键搜索表示为 unordered_map,等待顺序表示为队列,最近记录表示为堆栈,并且缺少值表示为可选。