← 返回首页

SIGNAL · POST

c++头文件之<utility>

约 7 分钟阅读 bajiu 青年大学习

📘 C++ <utility> 头文件详解

<utility> 是 C++ 中一个集合了多种通用小工具的头文件,包含:变量交换、移动语义工具、成对数据结构、小型辅助标签类型等。无论是写基础程序还是 STL、高级模板,都离不开 <utility>


1. <utility> 的作用概览

<utility> 提供以下功能:

🔹 常用工具函数

  • std::swap:交换两个变量的值
  • std::move:将对象转换为“右值引用”,触发移动语义
  • std::forward:用于模板的“完美转发”
  • std::exchange:设置新值并返回旧值
  • std::as_const:创建 const 引用

🔹 常用小型类型

  • std::pair:存储两个相关值
  • std::make_pair:自动推导类型并构造 pair
  • 一些用于容器内部构造的标签类型(例如 std::in_place_t

🔹 模板元编程工具

  • std::integer_sequence
  • std::index_sequence

这些用于编译期生成序列,多用于模板库实现。


2. std::pair —— 成对存储两个值

std::pair<T1, T2> 是一个简单的模板结构体,用于把两个类型不同的值绑定在一起。

2.1 定义形式

template<class T1, class T2>
struct pair {
    T1 first;
    T2 second;
};

2.2 基本使用

pair<int, string> p(10, "hello");

cout << p.first;   // 10
cout << p.second;  // hello

2.3 通过 make_pair 创建

auto p = make_pair(3, 4.5);  // 自动类型推导

2.4 常见用途

  • map 的键值对:map.insert(make_pair(key, value));
  • 坐标 pair:pair<int,int>(x, y)
  • 返回多个值

3. std::swap —— 通用交换函数

swap<utility> 最常用的函数之一。

3.1 用法

int a = 3, b = 5;
swap(a, b);   // a=5, b=3

3.2 底层原理

template<class T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

3.3 特点

  • 是模板,可以交换任意类型
  • 对 STL 容器优化过:交换是 **O(1)**(交换内部指针而不是逐个元素)

例如:

vector<int> a, b;
swap(a, b);  // 仅交换指针

用于矩阵原地转置:

swap(a[i][j], a[j][i]);

4. std::move —— 移动语义的核心工具

std::move 并不移动对象,而是将对象转换为右值引用,表示“可以被抢资源”。

4.1 示例

string a = "hello";
string b = std::move(a);

效果:

  • b 获得 a 的数据
  • a 被清空或处于“有效但未指定状态”

4.2 底层原理(简化)

template<class T>
T&& move(T& t) {
    return static_cast<T&&>(t);
}

5. std::forward —— 完美转发

用于模板,让参数保持原本的左值/右值属性。

5.1 示例(理解即可)

template<class T, class... Args>
T factory(Args&&... args) {
    return T(std::forward<Args>(args)...);
}

用途:

  • 保留参数的引用类别
  • 避免不必要的拷贝

属于进阶模板知识。


6. 多用途工具函数

6.1 std::exchange —— 设置新值并返回旧值

int x = 10;
int old = std::exchange(x, 42);

// old = 10
// x = 42

常用于状态机、swap+返回旧状态的场景。


6.2 std::as_const —— 把对象变成 const 引用

int x = 5;
auto& r = std::as_const(x);  // r: const int&

// r = 7; // ❌ 错误

7. 高阶:模板元编程工具

7.1 std::integer_sequence

在编译期生成一串整数。

7.2 std::index_sequence

主要用于展开 tuple:

template<typename Tuple, size_t... I>
void print(const Tuple& t, index_sequence<I...>) {
    ((cout << get<I>(t) << " "), ...);
}

这些通常用于:

  • tuple 展开
  • 完美转发
  • 编译期运算

8. 实用总结

下面是 <utility> 中最常用的部分:

名称 用途 初学者重要度
std::swap 通用变量交换 ⭐⭐⭐⭐⭐
std::pair 成对存储两个值 ⭐⭐⭐⭐
std::make_pair 更简单创建 pair ⭐⭐⭐⭐
std::move 触发移动语义 ⭐⭐⭐
std::forward 完美转发(模板) ⭐⭐
std::exchange 设置新值并返回旧值 ⭐⭐
std::as_const 创建 const 引用
std::index_sequence 高级模板

9. 示例:原地矩阵转置使用 <utility>

#include <iostream>
#include <utility>
using namespace std;

int main() {
    int n;
    cin >> n;

    int a[10][10];

    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            cin >> a[i][j];

    // 原地转置
    for (int i = 0; i < n; ++i)
        for (int j = i + 1; j < n; ++j)
            swap(a[i][j], a[j][i]);  // 来自 <utility>

    // 输出
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (j) cout << " ";
            cout << a[i][j];
        }
        cout << "\n";
    }
}