c++ std::tuple的用法
·
6. std::tuple
6.1 基本概述
std::tuple 是C++11引入的一个模板类,它允许将多个不同类型的值组合成一个单一的对象。类似于结构体,但不需要预先定义类型名称。tuple(元组)是一个固定大小的异构值集合,可以包含不同类型的元素。
- 它是 std::pair 的泛化版本,pair 只能保存两个元素,而 tuple 可以保存任意数量的元素。
- 本质是编译期定长、运行时不可变长的“通用结构体”。
6.2 用法
① 创建 Tuple
#include <tuple>
int main() {
// 创建⼀个包含3个元素的tuple: int, double, string
std::tuple<int, double, std::string> t1(10, 3.14, "hello");
// 使用 make_tuple 自动推导类型
auto t2 = std::make_tuple(20, 2.718, "world");
// C++17起可以使用类模板参数推导
std::tuple t3(30, 1.618, "cpp"); // ⾃动推导为tuple<int, double, const char*>
return 0;
}
- 可存放任意可复制/可移动类型;
- 大小在编译期固定,内存布局连续(与具体实现有关)。
② 元素访问:get<> + 结构化绑定
// 1. 索引版本
int& i = std::get<0>(t1); // 10
double& d = std::get<1>(t1); // 3.14
// 2. 类型版本(唯一)
std::string& s = std::get<std::string>(t); // hello
// 3. 修改
std::get<0> (t1) = 100; // 修改第一个元素
// 4. C++14 起可以通过类型访问(类型必须唯一)
std::cout << std::get<int>(t1) << std::endl;
std::cout << std::get<double>(t1) << std::endl;
// 5. C++17 结构化绑定
auto [id, score, name] = t; // 编译期展开,零开销
- 索引必须是编译期常量;越界 → 编译错误。
get<T>要求类型 T 在 tuple 里唯一。
③ 创建与拼接
| 工厂函数 | 说明 |
|---|---|
std::make_tuple(...) | 自动推导类型,避免手写长模板实参 |
std::tie(...) | 生成“左值引用 tuple”,用于多值返回/比较 |
std::tuple_cat(...) | 把多个 tuple 拼接成一个更大的 tuple |
示例:
int a = 1, b = 2;
auto t1 = std::tie(a, b); // tuple<int&, int&>
auto t2 = std::tuple_cat(t1, std::make_tuple(3.14));
// t2 类型 ≈ tuple<int&, int&, double>
// 解包
int x, y;
double z;
std::tie(x, y, z) = t2;
④ 比较与哈希
- 支持
==、!=、<、<=、>、>=——按字典序逐元素比较。 - C++20 起支持
std::hash<std::tuple<...>>(需逐个元素可哈希)。
6.3 典型用途
-
多值返回
std::tuple<bool, std::string, int> parse(const std::string& line);
auto [ok, name, age] = parse(line);
2. 一次性遍历多个容器
for (auto [it1, it2, idx] = std::tuple{v1.begin(), v2.begin(), 0};
it1 != v1.end() && it2 != v2.end();
++it1, ++it2, ++idx) { /* ... */ }
3.作为可变模板“容器”
模板元编程里常把参数包存进 tuple 再逐元素处理。
4.替代小结构体
就地一次性打包,无需手写 struct;配合结构化绑定可读性极高。
6.4 与 std::pair 的关系
pair只能存 2 个元素,有.first/.second;tuple可存任意数量,没有名字成员,全靠get<> / 结构化绑定;- 接口风格一致:
make_pairvsmake_tuple,tuple_cat也能拼接pair。
auto t = std::make_tuple(1, 2.0, 3L);
std::apply([](auto... args){ ((std::cout << args << ' '), ...); }, t);
std::apply把 tuple 元素解包成函数实参;- 配合
std::index_sequence可自行实现遍历、累加、打印等元函数。
.5 常见陷阱
- 元素默认构造:内置类型默认初始化为未定义值(若未显式提供)。
- 拷贝开销大:元素多且大对象时,按值传递 tuple 会深拷贝,考虑
std::ref或std::move。 - 编译期索引:
get<i>的i必须是常量表达式,运行时下标无法实现。
更多推荐



所有评论(0)