← SEARCHABLE ARCHIVE
C / C++ · 2026-07-01

从 C++ 基础到掌握 — 第 10 集

选择STL容器和可选

INTERACTIVE READING MODE →

该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。

游戏中有不同类型的数据,例如队伍列表、怪物搜索、生成队列和击杀记录。 所有数据都可以用单个向量解析,但如果您使用适合目的的数据结构,代码会更清晰。

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,等待顺序表示为队列,最近记录表示为堆栈,并且缺少值表示为可选。