← 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,等待順序表示為佇列,最近記錄表示為堆疊,並且缺少值表示為可選。