C++标准库头文件 utility 举例说明
C++标准库头文件 utility 举例说明
1. <utility>
<utility>
是 C++ 标准库头文件,提供 基础工具类与函数,主要包括 std::pair、std::move、std::forward、std::swap 等核心功能。以下是详细说明及代码示例:
1. std::pair:存储两个值的容器
基本用法
#include <utility>
#include <iostream>
int main() {
// 创建 pair
std::pair<int, std::string> student(1, "Alice");
// 访问元素
std::cout << "ID: " << student.first << ", Name: " << student.second << "\n";
// 结构化绑定(C++17)
auto [id, name] = student;
std::cout << "ID: " << id << ", Name: " << name << "\n";
return 0;
}
==============================================================
输出:
ID: 1, Name: Alice
ID: 1, Name: Alice
==============================================================
用途:存储键值对(如 map 的元素)、函数多返回值。
工厂函数 std::make_pair
auto point = std::make_pair(3.14, 2.71); // 自动推导类型
2. std::move:转换为右值引用(启用移动语义)
移动资源(避免拷贝)
#include <utility>
#include <vector>
int main() {
std::vector<int> src = {1, 2, 3};
std::vector<int> dest = std::move(src); // 移动构造
std::cout << "src size: " << src.size() << "\n"; // 0(资源已转移)
std::cout << "dest size: " << dest.size() << "\n"; // 3
return 0;
}
关键点:
std::move 将对象标记为“可移动”,调用移动构造函数/赋值运算符。
被移动后的对象处于有效但未定义状态(如 src 为空)。
3. std::forward:完美转发(保持值类别)
保持左值/右值属性
#include <utility>
#include <iostream>
template<typename T>
void wrapper(T&& arg) {
process(std::forward<T>(arg)); // 完美转发
}
void process(int& x) { std::cout << "Lvalue: " << x << "\n"; }
void process(int&& x) { std::cout << "Rvalue: " << x << "\n"; }
int main() {
int a = 10;
wrapper(a); // 传递左值 → 调用 process(int&)
wrapper(20); // 传递右值 → 调用 process(int&&)
return 0;
}
==========================================================
Lvalue: 10
Rvalue: 20
==========================================================
用途:在模板函数中保持参数原始类型(左值/右值)。
4. std::swap:交换两个对象的值
高效交换
#include <utility>
#include <vector>
int main() {
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5};
std::swap(vec1, vec2); // 交换内容
// vec1 = {4, 5}, vec2 = {1, 2, 3}
return 0;
}
底层优化:对标准库容器(如 vector)通常为 O(1) 时间复杂度(交换指针)。
5. std::exchange:赋值并返回旧值
原子性操作模拟
#include <utility>
#include <iostream>
int main() {
int x = 10;
int old_x = std::exchange(x, 20); // x=20,返回旧值10
std::cout << "old_x: " << old_x << ", x: " << x << "\n";
return 0;
}
========================================================
输出:
old_x: 10, x: 20
用途:状态机更新、线程安全编程。
========================================================
6. std::as_const:转换为常量引用(C++17)
防止意外修改
#include <utility>
void print(const std::string& s) {
// s 不能被修改
}
int main() {
std::string text = "Hello";
print(std::as_const(text)); // 显式传递 const 引用
return 0;
}
总结:
工具 | 用途 | 典型场景 |
---|---|---|
std::pair | 存储两个值 | 多返回值、键值对临时存储 |
std::move | 启用移动语义 | 资源转移(避免深拷贝) |
std::forward | 完美转发 | 通用引用(T&&)参数传递 |
std::swap | 高效交换对象内容 | 容器操作、排序算法 |
std::exchange | 赋值并返回旧值 | 状态更新、原子操作模拟 |
std::as_const | 添加 const 限定 | 强制只读访问 |
进阶技巧
-
结合结构化绑定(C++17):
auto [min, max] = std::minmax({3, 1, 4}); // min=1, max=4
-
自定义 swap:
struct Widget { int data; }; void swap(Widget& a, Widget& b) { std::swap(a.data, b.data); // 提供自定义交换 }