ZetCode

C++ map

最后修改于 2023 年 1 月 9 日

C++ map教程展示了如何在C++中操作map容器。

map是一个存储键/值对的容器。在其他编程语言中,map被称为关联容器、字典或哈希表。

map中的值通过其键来引用,而不是通过其在容器中的绝对位置。map中的键是唯一的。

C++ map简单示例

下面的示例展示了一些map的简单操作。

simple.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    cout << stones.size() << endl;

    stones.insert({6, "spinel"});

    cout << stones.size() << endl;

    for (const auto& stone: stones) {

      cout << stone.first << ": " << stone.second << endl;
    }

    stones.clear();

    cout << stones.size() << endl;
}

我们定义了一个stones map。

map<int, string> stones {
    {1, "citrine"},
    {2, "garnet"},
    {3, "topaz"},
    {4, "opal"},
    {5, "ametyst"}
};

stones map中,键是整数,值是字符串。

cout << stones.size() << endl;

我们使用size方法获取map的大小。

stones.insert({6, "spinel"});

使用insert方法插入一个新的stone。

for (const auto& stone: stones) {

    cout << stone.first << ": " << stone.second << endl;
}

我们使用for-range循环遍历map。

stones.clear();

使用clear移除所有键值对。

$ ./simple 
5
6
1: citrine
2: garnet
3: topaz
4: opal
5: ametyst
6: spinel
0

C++ map访问元素

可以通过[]运算符或at方法,使用键来访问值。访问不存在的键会抛出异常。

access.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    cout << stones.at(1) << endl;
    cout << stones[4] << endl;
}

我们使用[]at方法访问stones map中的两个值。

$ ./access 
citrine
opal

C++ map更新元素

下面的示例演示了更新值。

updating.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main() {

    map<int, string> words {
      {1, "sky"},
      {2, "blue"},
      {3, "cup"},
      {4, "nice"},
    };

    words[1] = "skylark";
    words.at(2) = "blues";

    for (const auto &word : words) {

        cout << "[" << word.first << ", " << word.second << "]" << endl;
    }
}

我们使用赋值运算符更新map中两个键值对的值。

$ ./updating 
[1, skylark]
[2, blues]
[3, cup]
[4, nice]

C++ map删除元素

使用erase方法从map中删除一个元素。

erasing.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    stones.erase(4);

    for (const auto& stone: stones) {

      cout << stone.first << ": " << stone.second << endl;
    }
}

我们删除键为4的键值对。

$ ./erasing 
1: citrine
2: garnet
3: topaz
5: ametyst

C++ map erase_if

erase_if方法删除所有满足给定谓词返回true的元素。该方法在C++20中引入。

erase_if.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main() {
  
    map<int, string> words {
      {1, "sky"},
      {2, "blue"},
      {3, "cup"},
      {4, "nice"},
      {5, "tall"},
      {6, "car"},
      {7, "top"}
    };

    erase_if(words, [](const auto& e) {
        return (e.second.size() == 3);
    });

    for (const auto &word : words) {

        cout << "[" << word.first << ", " << word.second << "]" << endl;
    }
}

在这个例子中,我们从map中删除了所有长度为三个字符的单词。

$ clang++ erase_if.cpp -o erase_if -std=c++20
$ ./erase_if 
[2, blue]
[4, nice]
[5, tall]

C++ map merge

merge方法合并两个map。该方法在C++20中引入。

merging.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main() {

    map<int, string> words {
      {1, "sky"},
      {2, "blue"},
      {3, "cup"}
    };

    map<int, string> words2 {
      {4, "nice"},
      {5, "tall"},
      {6, "car"},
      {7, "top"}
    };

    words.merge(words2);

    for (const auto &word : words) {

        cout << "[" << word.first << ", " << word.second << "]" << endl;
    }
}

我们合并了两个单词map。

$ ./merging 
[1, sky]
[2, blue]
[3, cup]
[4, nice]
[5, tall]
[6, car]
[7, top]

C++ map contains

contains方法检查是否存在具有指定键的元素。

contains.cpp
#include <iostream>
#include <map>

using std::string;
using std::map;
using std::endl;
using std::cout;

int main()
{
    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    for (int x: {2, 3, 7}) {
        if (stones.contains(x)) {
            cout << x << ": found" << endl;
        } else {
            cout << x << ": not found" << endl;
        }
    }
}

contains方法在C++20中引入。

$ clang++ contains.cpp -o contains -std=c++20
$ ./contains 
2: found
3: found
7: not found

C++ map使用while循环遍历

下面的示例使用while循环遍历map。

while_loop.cpp
#include <iostream>
#include <map>

using std::cout;
using std::endl;
using std::string;
using std::map;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    auto it = stones.cbegin();

    while (it != stones.cend()) {

        cout << "[" << it->first << ", "
                    << it->second << "]\n";
        it++;
    }

    cout << endl;

    return 0;
}

cbegin返回指向map开头的const迭代器,cend返回指向map末尾的const迭代器。

$ ./while_loop 
[1, citrine]
[2, garnet]
[3, topaz]
[4, opal]
[5, ametyst]

C++ map使用经典for循环遍历

下面的示例使用经典的for循环形式遍历map。

classic_for.cpp
#include <iostream>
#include <map>

using std::cout;
using std::endl;
using std::string;
using std::map;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    for (auto it = stones.cbegin(); it != stones.cend(); it++) {

        cout << "[" << it->first << ", "
                    << it->second << "]"
                    << endl;
    }

    cout << endl;

    return 0;
}

我们使用经典的for循环遍历map中的stones。

C++ map使用for-range循环遍历

下面的示例使用for-range循环遍历map元素。

for_range.cpp
#include <iostream>
#include <map>

using std::cout;
using std::endl;
using std::string;
using std::map;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    for (const auto &stone : stones) {

        cout << "[" << stone.first << ", " << stone.second << "]\n";
    }

    cout << endl;

    return 0;
}

For-range循环在C++11中引入。

下一个示例展示了另一种for-range形式。

for_range2.cpp
#include <iostream>
#include <map>

using std::cout;
using std::endl;
using std::string;
using std::map;

int main() {

    map<int, string> stones {
      {1, "citrine"},
      {2, "garnet"},
      {3, "topaz"},
      {4, "opal"},
      {5, "ametyst"}
    };

    // decomposition C++17
    for (const auto& [key, value] : stones) {

        cout << "[" << key << ", " << value << "]\n";
    }

    cout << endl;

    return 0;
}

本例中使用的解构操作在C++17中引入。

在本文中,我们学习了如何在C++中操作map容器。