当前位置: 首页 > news >正文

C++: map和set

目录

set

multiset

map

mulimap

pair


关联式容器与序列式容器

序列式容器 (Sequence Containers)

  • 关注元素的位置和插入顺序

  • 典型的"先来后到"顺序存储

关联式容器 (Associative Containers)

  • 关注元素之间的关联关系

  • 基于键值对(key-value)的快速查找

具体容器类型对比

        关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是结构的 键值对,在数据检索时比序列式容器效率更高

键值对:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代 表键值,value表示与key对应的信息。

SGI-STL中关于键值对的定义:

        根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。

        树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果。

set

set的介绍

set的模板参数列表

T:set中存放元素的类型,实际在底层存储<value, value>的键值对

Compare: set中元素默认按照小于来比较

Alloc: set中元素空间的管理方式,使用STL提供的空间配置管理器

set的构造

set容器常见的接口

基本构造和赋值:operator= 赋值操作

#include <iostream>
#include <set>
using namespace std;void testAssignment() {set<int> s1 = {1, 3, 5, 7, 9};set<int> s2;s2 = s1;  // 赋值操作cout << "s2 after assignment: ";for (int x : s2) cout << x << " ";  // 1 3 5 7 9cout << endl;// 移动赋值set<int> s3 = move(s2);cout << "s3 after move: ";for (int x : s3) cout << x << " ";  // 1 3 5 7 9cout << endl;cout << "s2 size after move: " << s2.size() << endl;  // 0
}

迭代器接口:正向和反向迭代器

void testIterators() {set<int> s = {10, 20, 30, 40, 50};cout << "正向遍历: ";for (auto it = s.begin(); it != s.end(); ++it) {cout << *it << " ";  // 10 20 30 40 50}cout << endl;cout << "反向遍历: ";for (auto it = s.rbegin(); it != s.rend(); ++it) {cout << *it << " ";  // 50 40 30 20 10}cout << endl;// C++11引入的const迭代器cout << "常量正向遍历: ";for (auto it = s.cbegin(); it != s.cend(); ++it) {// *it = 100;  // 错误:不能修改常量迭代器指向的值cout << *it << " ";}cout << endl;
}

容量查询:empty() 和 size()

void testCapacity() {set<int> s;cout << "空set - empty: " << s.empty() << ", size: " << s.size() << endl;s.insert({1, 2, 3});cout << "插入后 - empty: " << s.empty() << ", size: " << s.size() << endl;
}

insert() 插入操作

        set::insert 的返回值是一个 pair类型,具体定义为:

这是一个模板类,包含两个成员:

  • first: 迭代器(iterator),指向被插入的元素

  • second: 布尔值(bool),表示插入是否成功

void testInsert() {set<int> s;// 方式1:直接插入值auto result1 = s.insert(10);cout << "插入10: " << (result1.second ? "成功" : "失败") << ", 插入位置的值: " << *result1.first << endl;// result1 的类型: pair<set<int>::iterator, bool>// result1.first: 指向元素10的迭代器// result1.second: true (因为10不存在,插入成功)// 方式2:插入已存在值(会失败)auto result2 = s.insert(10);cout << "再次插入10: " << (result2.second ? "成功" : "失败") << endl;// 方式3:批量插入s.insert({5, 15, 25, 35});cout << "最终set内容: ";for (int x : s) cout << x << " ";  // 5 10 15 25 35cout << endl;
}

erase() 删除操作

void testErase() {set<int> s = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 方式1:通过值删除size_t count1 = s.erase(5);  // 返回删除的元素个数cout << "删除值5,删除了 " << count1 << " 个元素" << endl;// 方式2:通过迭代器删除auto it = s.find(3);if (it != s.end()) {s.erase(it);  // 安全删除cout << "通过迭代器删除3" << endl;}// 方式3:删除不存在的值(不会报错)size_t count2 = s.erase(100);cout << "删除不存在的值100,删除了 " << count2 << " 个元素" << endl;// 方式4:删除范围auto first = s.find(6);auto last = s.find(8);if (first != s.end() && last != s.end()) {s.erase(first, last);  // 删除[6, 8),注意是前闭后开}cout << "删除后set内容: ";for (int x : s) cout << x << " ";  // 1 2 4 8 9cout << endl;
}

返回值类型总结

查找操作(核心功能):find() 查找

void testFind() {set<int> s = {10, 20, 30, 40, 50};// set专用的find(二分查找 O(log n))auto it = s.find(30);if (it != s.end()) {cout << "找到30: " << *it << endl;} else {cout << "未找到30" << endl;}// 与std::find对比(线性查找 O(n))auto it2 = find(s.begin(), s.end(), 30);if (it2 != s.end()) {cout << "std::find也找到30: " << *it2 << endl;}// 查找不存在的值auto it3 = s.find(100);if (it3 == s.end()) {cout << "100不存在于set中" << endl;}
}

lower_bound() 和 upper_bound()

void testBounds() {set<int> s = {10, 20, 30, 40, 50};// lower_bound: 第一个 >= 值的元素auto lb = s.lower_bound(25);if (lb != s.end()) {cout << "lower_bound(25): " << *lb << endl;  // 30}// upper_bound: 第一个 > 值的元素  auto ub = s.upper_bound(25);if (ub != s.end()) {cout << "upper_bound(25): " << *ub << endl;  // 30}// 查找边界值cout << "lower_bound(30): " << *s.lower_bound(30) << endl;  // 30cout << "upper_bound(30): " << *s.upper_bound(30) << endl;  // 40// 查找超出范围的值auto beyond = s.upper_bound(60);if (beyond == s.end()) {cout << "upper_bound(60) 返回end()" << endl;}
}

equal_range() 相等范围

void testEqualRange() {set<int> s = {10, 20, 30, 40, 50};// equal_range返回pair<lower_bound, upper_bound>auto range = s.equal_range(25);cout << "equal_range(25): [" << *range.first << ", " << *range.second << ")" << endl;// 输出: [30, 30) 因为25不在set中// 对于存在的值range = s.equal_range(30);cout << "equal_range(30): [" << *range.first << ", " << *range.second << ")" << endl;// 输出: [30, 40)// 可以用来遍历某个范围内的元素cout << "20到40之间的元素: ";range = s.equal_range(20);range.second = s.upper_bound(40);  // 手动调整上界for (auto it = range.first; it != range.second; ++it) {cout << *it << " ";  // 20 30 40}cout << endl;
}

count() 计数

void testCount() {set<int> s = {1, 2, 3, 4, 5};// set中count只能返回0或1(因为元素唯一)cout << "count(3): " << s.count(3) << endl;  // 1cout << "count(10): " << s.count(10) << endl; // 0// 与multiset对比multiset<int> ms = {1, 2, 2, 3, 3, 3};cout << "multiset count(2): " << ms.count(2) << endl;  // 2cout << "multiset count(3): " << ms.count(3) << endl;  // 3
}

swap() 和 clear()

void testSwapClear() {set<int> s1 = {1, 3, 5};set<int> s2 = {2, 4, 6};cout << "交换前 - s1: ";for (int x : s1) cout << x << " ";  // 1 3 5cout << ", s2: ";for (int x : s2) cout << x << " ";  // 2 4 6cout << endl;s1.swap(s2);  // 交换两个set的内容cout << "交换后 - s1: ";for (int x : s1) cout << x << " ";  // 2 4 6cout << ", s2: ";for (int x : s2) cout << x << " ";  // 1 3 5cout << endl;s1.clear();  // 清空setcout << "清空后s1的size: " << s1.size() << endl;  // 0
}

完整测试代码

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;int main() {cout << "=== set容器接口测试 ===" << endl;testAssignment();testIterators(); testCapacity();testInsert();testErase();testFind();testBounds();testEqualRange();testCount();testSwapClear();// 验证自动排序和去重特性cout << "\n=== 自动排序和去重验证 ===" << endl;set<int> s = {5, 2, 8, 2, 5, 1, 8, 9};cout << "插入{5,2,8,2,5,1,8,9}后: ";for (int x : s) cout << x << " ";  // 1 2 5 8 9cout << endl;return 0;
}

重要特性总结

1. 自动排序和去重

set<int> s = {3, 1, 4, 1, 5, 9, 2, 6};
// 实际存储: 1 2 3 4 5 6 9(自动排序+去重)

2. 查找性能对比

set<int> large_set;
// 插入大量数据...// 专用find - O(log n) - 推荐
auto it1 = large_set.find(target);// 通用find - O(n) - 不推荐  
auto it2 = find(large_set.begin(), large_set.end(), target);

3. 安全删除模式

// 安全删除模式
auto it = s.find(value);
if (it != s.end()) {s.erase(it);  // 安全,迭代器有效才删除
}// 直接删除值(更简洁)
s.erase(value);  // 如果值不存在,不会报错

使用建议

  1. 需要快速查找时优先使用set专用find

  2. 需要范围查询时使用lower_bound/upper_bound/equal_range

  3. 删除元素时优先使用值删除,避免迭代器失效问题

  4. 需要保持插入顺序时不要使用set,选择vector或list

  5. 需要重复元素时使用multiset

set的这些特性使其成为需要快速查找、自动排序和唯一元素的理想选择!

multiset

multiset 确实与 set 的主要区别就是允许重复元素,其他接口基本一致。

1.

1.1 基本特性对比

void basicDifference() {cout << "=== set vs multiset 基本区别 ===" << endl;// set: 自动去重set<int> s = {1, 2, 2, 3, 3, 3};cout << "set 内容: ";for (int x : s) cout << x << " ";  // 1 2 3cout << ", 大小: " << s.size() << endl;  // 3// multiset: 允许重复multiset<int> ms = {1, 2, 2, 3, 3, 3};cout << "multiset 内容: ";for (int x : ms) cout << x << " ";  // 1 2 2 3 3 3cout << ", 大小: " << ms.size() << endl;  // 6
}

1.2 insert() 行为的区别

void testInsertDifference() {cout << "\n=== insert() 行为区别 ===" << endl;set<int> s;multiset<int> ms;// set插入重复元素auto s_result1 = s.insert(10);cout << "set第一次插入10: " << (s_result1.second ? "成功" : "失败") << endl;  // 成功auto s_result2 = s.insert(10);cout << "set第二次插入10: " << (s_result2.second ? "成功" : "失败") << endl;  // 失败// multiset插入重复元素auto ms_result1 = ms.insert(10);cout << "multiset第一次插入10: 成功" << endl;auto ms_result2 = ms.insert(10);cout << "multiset第二次插入10: 成功" << endl;cout << "set大小: " << s.size() << endl;     // 1cout << "multiset大小: " << ms.size() << endl; // 2
}

2. multiset 特有的应用场景

2.1 count() 的实际应用

void testCountUsage() {cout << "\n=== count() 的实际应用 ===" << endl;// 成绩统计示例multiset<int> scores = {85, 92, 78, 85, 90, 85, 78, 95};cout << "所有成绩: ";for (int score : scores) cout << score << " ";cout << endl;// 统计每个分数出现的次数cout << "成绩统计:" << endl;auto it = scores.begin();while (it != scores.end()) {int current_score = *it;int count = scores.count(current_score);cout << "分数 " << current_score << ": " << count << " 次" << endl;// 跳过相同的分数advance(it, count);}// 查找特定分数的出现次数int target_score = 85;cout << "分数 " << target_score << " 出现了 " << scores.count(target_score) << " 次" << endl;
}

2.2 equal_range() 的实际应用

void testEqualRangeUsage() {cout << "\n=== equal_range() 的实际应用 ===" << endl;multiset<int> data = {10, 20, 20, 20, 30, 30, 40, 50, 50, 50};// 查找所有等于20的元素auto range = data.equal_range(20);cout << "所有等于20的元素: ";for (auto it = range.first; it != range.second; ++it) {cout << *it << " ";}cout << endl;// 查找范围 [30, 50) 的元素auto lower = data.lower_bound(30);  // 第一个 >= 30 的元素auto upper = data.upper_bound(49); // 第一个 > 49 的元素cout << "范围 [30, 50) 的元素: ";for (auto it = lower; it != upper; ++it) {cout << *it << " ";  // 30, 30, 40}cout << endl;// 使用equal_range处理不存在的值auto not_found_range = data.equal_range(25);if (not_found_range.first == not_found_range.second) {cout << "元素25不存在" << endl;}
}

3. multiset 专有操作示例

3.1 删除特定数量的重复元素

void testMultisetErase() {cout << "\n=== multiset 特有的删除操作 ===" << endl;multiset<int> ms = {1, 2, 2, 2, 3, 3, 4, 4, 4, 4};cout << "原始multiset: ";for (int x : ms) cout << x << " ";cout << ", 大小: " << ms.size() << endl;// 删除所有值为2的元素size_t removed = ms.erase(2);cout << "删除所有2,删除了 " << removed << " 个元素" << endl;cout << "删除后: ";for (int x : ms) cout << x << " ";  // 1 3 3 4 4 4 4cout << endl;// 只删除第一个3auto it = ms.find(3);if (it != ms.end()) {ms.erase(it);  // 只删除迭代器指向的那个3}cout << "删除一个3后: ";for (int x : ms) cout << x << " ";  // 1 3 4 4 4 4cout << endl;
}

删除某个数字,就是删除所有这个数字。

3.2 处理重复元素的迭代技巧

void testIterationTechniques() {cout << "\n=== 处理重复元素的迭代技巧 ===" << endl;multiset<string> words = {"apple", "banana", "apple", "cherry", "apple", "date"};// 方法1:使用equal_range遍历特定值的所有出现cout << "所有'apple'的出现: ";auto apple_range = words.equal_range("apple");for (auto it = apple_range.first; it != apple_range.second; ++it) {cout << *it << " ";}cout << endl;// 方法2:跳过重复元素的遍历cout << "不重复遍历: ";auto it = words.begin();while (it != words.end()) {string current_word = *it;cout << current_word << "(" << words.count(current_word) << ") ";// 跳到下一个不同的单词it = words.upper_bound(current_word);}cout << endl;
}

使用建议

void usageRecommendations() {cout << "\n=== 使用建议 ===" << endl;cout << "适合使用multiset的场景:" << endl;cout << "1. 需要维护排序且允许重复的集合" << endl;cout << "2. 需要频繁统计元素出现次数" << endl;cout << "3. 需要快速查找某个范围内的所有元素" << endl;cout << "4. 需要保持插入顺序但允许重复(与vector不同)" << endl;cout << "\n不适合使用multiset的场景:" << endl;cout << "1. 需要唯一元素 → 使用set" << endl;cout << "2. 需要极快插入且不关心顺序 → 使用unordered_multiset" << endl;cout << "3. 只需要简单集合操作 → 使用vector + sort" << endl;
}

完整测试代码

int main()
{//cout << " === set容器接口测试 === " << endl;/*testAssignment();*//* testAssignment();*///testCapacity();/*testInsert();*///testErase();/*testFind();*//*testBounds();*///testEqualRange();//testCount();//testSwapClear();basicDifference();testInsertDifference();testCountUsage();testEqualRangeUsage();testMultisetErase();testIterationTechniques();usageRecommendations();return 0;
}

multiset 的核心特点:

  1. 允许重复元素:与set最主要的区别

  2. 自动排序:保持元素有序

  3. 高效操作:插入、删除、查找都是O(log n)

  4. 特有功能:count()和equal_range()在multiset中特别有用

关键接口对比:

操作

set

multiset

insert(value)

可能失败(重复时)

总是成功

count(value)

返回0或1

返回实际出现次数

equal_range(value)

范围最多1个元素

可能包含多个元素

erase(value)

删除0或1个元素

删除所有该值的元素

一句话总结:当您需要维护一个有序且允许重复的集合时,multiset是最佳选择!

map

map的介绍

map与set的基本区别

#include <iostream>
#include <map>
#include <set>
using namespace std;void basicDifference() {cout << "=== map vs set 基本区别 ===" << endl;// set: 只存储键(key)set<string> s = {"apple", "banana", "cherry"};cout << "set内容: ";for (const auto& key : s) cout << key << " ";  // apple banana cherrycout << endl;// map: 存储键值对(key-value)map<string, int> m = {{"apple", 3}, {"banana", 2}, {"cherry", 5}};cout << "map内容: ";for (const auto& pair : m) {cout << pair.first << ":" << pair.second << " ";          // apple:3 banana:2 cherry:5}cout << endl;
}

map的模板参数列表

key: 键值对中key的类型

T: 键值对中value的类型

Compare: 比较器的类型。map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递。如果无法比较时(自定义类型),需要用户 自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Alloc:通过空间配置器来申请底层空间,不需要用户传递

注意:使用map时,需要包含头文件

map的构造

map的迭代器

map的容量与元素访问

问题:当key不在map中时,通过operator获取对应value时会发生什么问题?

void testAutoInsertion() {map<string, int> scores = {{"Alice", 90}, {"Bob", 85}};cout << "操作前map大小: " << scores.size() << endl;  // 2// 访问不存在的keycout << "Charlie的分数: " << charlie_score << endl;  // 输出: 0cout << "操作后map大小: " << scores.size() << endl;  // 3 - 自动增加了!}

operator[]调用等价于:

(*((this->insert(make_pair(k, mapped_type()))).first)).second

让我们分解理解

void explainEquivalentCode() {map<string, int> scores;// 分解operator["Charlie"]的等价操作auto result = scores.insert(make_pair("Charlie", int())); // 1. 尝试插入pair("Charlie", 0)// 2. 如果key已存在,insert返回已存在元素的迭代器// 3. 如果key不存在,插入新元素并返回新元素的迭代器int& value_ref = (*(result.first)).second;// 获取映射值的引用cout << "插入结果: " << (result.second ? "成功" : "失败") << endl;cout << "获取的值: " << value_ref << endl;
}

当key不存在时,operator[]用默认 value与key构造键值对然后插入,返回该默认value。at()函数直接抛异常。

构造和初始化

void testMapConstruction() {cout << "\n=== map的构造方式 ===" << endl;// 方式1:默认构造map<string, int> m1;// 方式2:初始化列表map<string, int> m2 = {{"Alice", 90},{"Bob", 85},{"Charlie", 92}};// 方式3:拷贝构造map<string, int> m3(m2);// 方式4:范围构造map<string, int> m4(m2.begin(), m2.end());cout << "m2内容: ";for (const auto& p : m2) {cout << p.first << ":" << p.second << " ";}cout << endl;
}

插入操作

void testInsertOperations() {cout << "\n=== 插入操作对比 ===" << endl;map<string, int> m;// map插入:需要键值对auto m_result = m.insert({ "apple", 3 });  // 使用paircout << "map插入结果: " << (m_result.second ? "成功" : "失败") << endl;for (const auto& p : m) {cout << p.first << ":" << p.second << " ";}cout << endl;
}

访问操作(map特有功能)

void testAccessOperations() {cout << "\n=== 访问操作(map特有)===" << endl;map<string, int> scores = {{"Alice", 90}, {"Bob", 85}};// 1. operator[](最重要、最常用)cout << "Alice的分数: " << scores["Alice"] << endl;  // 90// operator[]的特殊行为:key不存在时自动插入cout << "Charlie的分数: " << scores["Charlie"] << endl;  // 0(自动插入)cout << "map大小: " << scores.size() << endl;  // 3// 2. at()方法(安全访问)try {cout << "Bob的分数: " << scores.at("Bob") << endl;  // 85cout << "David的分数: " << scores.at("David") << endl;  // 抛出异常} catch (const out_of_range& e) {cout << "异常: " << e.what() << endl;}// 3. 通过迭代器访问auto it = scores.find("Alice");if (it != scores.end()) {cout << "通过迭代器访问: " << it->first << ":" << it->second << endl;}
}

查找操作

void testFindOperations() {cout << "\n=== 查找操作对比 ===" << endl;set<string> s = {"apple", "banana", "cherry"};map<string, int> m = {{"apple", 3}, {"banana", 2}, {"cherry", 5}};// set查找:返回键的迭代器auto s_it = s.find("banana");if (s_it != s.end()) {cout << "set找到: " << *s_it << endl;}// map查找:返回键值对的迭代器auto m_it = m.find("banana");if (m_it != m.end()) {cout << "map找到: " << m_it->first << ":" << m_it->second << endl;}// map特有的查找模式string key = "apple";if (m.count(key) > 0) {  // 检查键是否存在cout << key << "的值为: " << m[key] << endl;  // 安全访问}
}

删除操作

void testEraseOperations() {cout << "\n=== 删除操作 ===" << endl;map<string, int> m = {{"A", 1}, {"B", 2}, {"C", 3}, {"D", 4}, {"E", 5}};// 1. 通过键删除size_t count = m.erase("B");  // 返回删除的元素个数cout << "删除了 " << count << " 个元素" << endl;// 2. 通过迭代器删除auto it = m.find("C");if (it != m.end()) {m.erase(it);}// 3. 删除范围auto first = m.find("D");if (first != m.end()) {m.erase(first, m.end());}cout << "删除后剩余: ";for (const auto& p : m) {cout << p.first << " ";}cout << endl;
}

map特有功能讲解

operator[] 的妙用

void testOperatorBracket() {cout << "\n=== operator[] 的实用技巧 ===" << endl;// 1. 单词计数(经典用法)string text = "apple banana apple cherry banana apple";map<string, int> wordCount;stringstream ss(text);string word;while (ss >> word) {wordCount[word]++;  // 自动初始化为0然后递增}cout << "单词统计: ";for (const auto& p : wordCount) {cout << p.first << ":" << p.second << " ";}cout << endl;// 2. 默认值设置map<string, string> config;string value = config["timeout"];  // 自动插入空字符串cout << "timeout配置: '" << value << "'" << endl;// 3. 链式访问(需要谨慎)map<string, map<string, int>> nestedMap;nestedMap["user1"]["score"] = 100;  // 自动创建内层mapcout << "嵌套访问: " << nestedMap["user1"]["score"] << endl;
}

范围查询(map特有优势)

void testRangeQueries() {cout << "\n=== 范围查询 ===" << endl;map<int, string> students = {{101, "Alice"}, {102, "Bob"}, {105, "Charlie"}, {108, "David"}, {110, "Eve"}};// 查找学号在[103, 109)范围内的学生auto lower = students.lower_bound(103);  // 第一个 >= 103auto upper = students.upper_bound(109);   // 第一个 > 109cout << "学号103-109的学生: ";for (auto it = lower; it != upper; ++it) {cout << it->first << ":" << it->second << " ";  // 105:Charlie 108:David}cout << endl;// equal_range获取相等键的范围(在multimap中更有用)auto range = students.equal_range(105);if (range.first != range.second) {cout << "学号105的学生: " << range.first->second << endl;}
}

mulimap

mulimap的介绍

mulimap的使用

operator[]的语义是"获取或设置指定键的值",但在multimap中,一个键对应多个值,这导致了根本性的语义歧义。所以multimap中没有重载operator[]操作。

#include <iostream>
#include <map>
#include <string>
using namespace std;void oneToManyMapping() {cout << "=== 一对多关系映射 ===" << endl;// 学生与课程成绩的映射multimap<string, string> studentCourses;// 添加选课关系studentCourses.insert({"Alice", "Math"});studentCourses.insert({"Alice", "Physics"});studentCourses.insert({"Bob", "Chemistry"});studentCourses.insert({"Alice", "Computer Science"});studentCourses.insert({"Bob", "Math"});// 查询Alice的所有课程cout << "Alice的课程: ";auto range = studentCourses.equal_range("Alice");for (auto it = range.first; it != range.second; ++it) {cout << it->second << " ";}cout << endl;// 查询Bob的所有课程cout << "Bob的课程: ";range = studentCourses.equal_range("Bob");for (auto it = range.first; it != range.second; ++it) {cout << it->second << " ";}cout << endl;
}

pair

想象一下 pair 就像一张名片:

  • 名片上有两个主要信息:姓名 + 电话号码

  • 这两个信息是相关的,总是一起出现

  • 但名片就是一个独立的东西

        注意:头文件是utility。pair就是一个“数据对”,可以把任意两个值打包在一起,不管它们是什么类型。

代码中的基本形式

#include <iostream>
#include <utility>  // 包含pair的头文件
using namespace std;int main() {// 创建一个pair:就像创建一张名片pair<string, string> businessCard = {"张三", "138-1234-5678"};// 访问pair中的信息cout << "姓名: " << businessCard.first << endl;    // 张三cout << "电话: " << businessCard.second << endl;   // 138-1234-5678return 0;
}

pair 与 map 的根本区别,map是由很多pair组成的。

http://www.dtcms.com/a/598823.html

相关文章:

  • 河南映天建设网站临沂网站建设企业
  • 建设银行广西分行招聘网站织梦怎么做企业网站
  • 网页制作工具的选择与网站整体风格没有关系建设网站需要什么资质
  • 中国企业网站建设案例中华香烟网上商城
  • TSMC 28nm EFP.Mx.S.1 DRC该如何fix
  • 基于Matlab的欧拉法和龙格-库塔法微分方程求解
  • 基于单片机的预约保温型智能电饭锅控制系统设计与实现
  • 做绿色产品的网站wordpress 热门排序
  • 上市公司网站建设中山seo排名优化
  • 十二、深度学习里程碑式模型:AlexNet
  • 做旅游销售网站平台pptwordpress去水印插件
  • 做汽车介绍视频的网站吗企业信息系统架构
  • 涟源市建设局网站wordpress另一更新正在运行
  • 网站维护什么情况莆田社交网站
  • Redisson 和 Jedis 的区别
  • 网页制作和网站开发实验报告网站建设续费催款通知书
  • 爬虫案例之爬取当当网书籍信息(最新独特版)
  • 建设银行网站怎么看不见余额wordpress page id
  • 【目标检测】VS2026+QT6.9+ONNXruntime+OPENCV+YOLO11(详细注释)(附测试模型和图像)
  • 一文掌握 MCP 上下文协议:从理论到实践
  • 东莞建设网企业沟通平台深圳免费网站优化网络推广
  • 免费有趣的网站一个学校怎么制作网站
  • 2025-11-11 hetao1733837的刷题记录
  • Solidworks练习45-旋转、拉伸、阵列
  • npm : 无法加载文件 D:\nvm\nodejs\npm.ps1,因为在此系统上禁止运行脚本问题解决
  • 无锡做网站中企动力软文营销的定义
  • 微算法科技(NASDAQ MLGO)结合权威证明(PoA)机制与权益证明(PoS)/工作量证明(PoW),平衡效率与去中心化
  • 定西市网站建设企业北京建设工程网站
  • 龙华网站建设推广平台广东二次感染最新消息
  • 基于ELM算法在近红外光谱和拉曼光谱数据处理