49 C++ STL模板库18-类模板-pair
C++ STL模板库18-类模板-pair
文章目录
- C++ STL模板库18-类模板-pair
- 一、本质定义
- 二、核心作用
- 三、 用法示例
std::pair
是 C++ 标准库中定义于 <utility>
头文件的模板类,用于将两个不同类型的值组合成单一对象,实现异构数据的关联存储。
一、本质定义
template <class T1, class T2>
struct pair {T1 first; // 第一个元素 T2 second; // 第二个元素
};
- 二元组结构:存储任意两个类型
T1
和T2
的值 - 零开销抽象:编译时确定类型,无运行时性能损耗
- 标准库基石:被广泛应用于 STL 容器和算法
二、核心作用
-
关联异构数据
将逻辑相关的两个值绑定为单一实体:// 坐标点 (x, y) std::pair<double, double> point(3.5, 7.2);
-
函数多返回值
替代结构体,简化多值返回:std::pair<bool, std::string> validateUser(int id) {if (id > 0) return {true, "Valid"};return {false, "Invalid ID"}; }
-
STL 容器元素
-
std::map
/std::unordered_map
的键值对元素:std::map<int, std::string> employees = {{101, "Alice"}, // pair<int, string>{102, "Bob"} };
-
排序容器中的复合数据:
std::vector<std::pair<int, std::string>> scores = {{95, "Math"}, {88, "English"} }; std::sort(scores.begin(), scores.end()); // 按int排序
-
-
高效资源传递
支持移动语义避免拷贝:auto createResource() {std::vector<int> data = {1, 2, 3};std::string name = "Data";return std::make_pair(std::move(data), std::move(name)); // 零拷贝返回 }
三、 用法示例
#include <utility>
#include <string>
#include <iostream>
#include <tuple>
#include <vector>struct Data {Data(int a, double b) : x(a), y(b) {}int x;double y;
};int main() {//1.构造与初始化// 1. 默认构造:成员值初始化std::pair<int, std::string> p1;std::cout << "p1: (" << p1.first << ", " << p1.second << ")\n"; // (0, "")// 2. 直接初始化std::pair<int, double> p2(42, 3.14);std::cout << "p2: (" << p2.first << ", " << p2.second << ")\n"; // (42, 3.14)// 3. 移动构造std::string s = "hello";std::pair<int, std::string> p3(100, std::move(s));std::cout << "p3: (" << p3.first << ", " << p3.second << ")\n"; // (100, "hello")std::cout << "s after move: " << s << "\n"; // ""(空,资源已转移)// 4. 通用构造(完美转发)std::pair<double, long> p4(2.718f, 7); // float→double, int→longstd::cout << "p4: (" << p4.first << ", " << p4.second << ")\n"; // (2.718, 7)// 5. 复制/移动构造(从其他pair)auto p5 = p2; // 复制auto p6 = std::move(p3); // 移动// 6. 分段构造(避免冗余拷贝)std::pair<Data, Data> p7(std::piecewise_construct,std::forward_as_tuple(1, 2.0), // 构造第一个Data: Data(1, 2.0)std::forward_as_tuple(3, 4.0) // 构造第二个Data: Data(3, 4.0));std::cout << "p7: ((" << p7.first.x << "," << p7.first.y << "), ("<< p7.second.x << "," << p7.second.y << "))\n"; // ((1,2),(3,4))// 2.赋值操作{// 1. 复制赋值std::pair<int, int> p8(10, 20);auto p9 = p8; // p9 = (10,20)// 2. 移动赋值std::pair<std::string, std::string> p10("A", "B");std::pair<std::string, std::string> p11;p11 = std::move(p10); // p11 = ("A","B"), p10变为("","")// 3. 通用赋值(类型转换)std::pair<int, double> src(5, 10.5);std::pair<long, float> dst;dst = src; // int→long, double→floatstd::cout << "dst: (" << dst.first << ", " << dst.second << ")\n"; // (5, 10.5)}//3. 元素访问{std::pair<int, std::string> p(42, "answer");// 1. 直接访问成员p.first = 100;p.second = "changed";std::cout << "p: (" << p.first << ", " << p.second << ")\n"; // (100, "changed")// 2. 结构化绑定(C++17)auto [num, str] = p;std::cout << "num=" << num << ", str=" << str << "\n"; // num=100, str=changed// 3. 使用 get<N>() 访问auto& x = std::get<0>(p); // x是first的引用auto& y = std::get<1>(p); // y是second的引用x = 200;std::cout << "p.first after get: " << p.first << "\n"; // 200}//4. 交换操作{std::pair<int, std::string> a(1, "apple");std::pair<int, std::string> b(2, "banana");// 1. 成员函数 swapa.swap(b); std::cout << "a: (" << a.first << ", " << a.second << ")\n"; // (2, "banana")std::cout << "b: (" << b.first << ", " << b.second << ")\n"; // (1, "apple")// 2. 非成员函数 swapstd::swap(a, b); // 换回原值std::cout << "a: " << a.first << ", b: " << b.first << "\n"; // a:1, b:2}//5. 比较操作{std::pair<int, int> x(1, 2);std::pair<int, int> y(1, 3);std::pair<int, int> z(2, 1);std::cout << (x < y) << "\n"; //first相等(1==1),second:2<3 → truestd::cout << (x <= y) << "\n"; //1std::cout << (y > x) << "\n"; //1std::cout << (z > x) << "\n"; //1std::cout << (x != std::make_pair(1, 99)) << "\n"; //1std::cout << (x == std::make_pair(1, 2)) << "\n"; //1}//6. 实用函数{// 1. make_pair 自动推导类型auto p = std::make_pair(42, 3.14); // std::pair<int, double>auto q = std::make_pair("text", 1); // std::pair<const char*, int>// 2. 在容器中使用std::vector<std::pair<int, std::string>> vec;vec.emplace_back(1, "one"); // 直接构造pair(高效)vec.push_back(std::make_pair(2, "two"));// 3. 作为函数返回值auto findInMap = [](const auto& map, int key) -> std::pair<bool, decltype(map.begin())> {auto it = map.find(key); return {it != map.end(), it};};std::map<int, std::string> m{{1, "a"}, {2, "b"}};auto [found, it] = findInMap(m, 2);if (found) std::cout << "Found: " << it->second << "\n"; // "b"}}