array 与 tuple
定义与作用
std::array(C++11)是对原生数组的零开销封装——大小编译期确定,支持迭代器和标准容器接口。std::tuple(C++11)是固定大小异构集合,可存储任意类型的组合。
#include <array>
#include <tuple>
std::array<int, 5> arr{1, 2, 3, 4, 5}; // 编译期大小,栈上分配
std::tuple<std::string, int, double> t("大翔", 28, 188888.88);
| 特性 | array | tuple |
|---|---|---|
| 元素类型 | 同构 | 异构(任意组合) |
| 大小 | 编译期确定 | 编译期确定 |
| 内存 | 栈上连续 | 栈上聚合 |
| 访问 | [] / at() | get<N>() / get<Type>() |
| 主要用途 | 替代原生数组 | 多返回值、打包参数 |
核心原理
array vs 原生数组
tuple 的递归继承实现
完整示例
示例一:飞翔科技月度营收统计
场景说明:高英用 array 存储飞翔科技 2026 年前 6 个月的营收数据,避免使用原生数组。
#include <iostream>
#include <array>
#include <algorithm>
#include <numeric>
#include <iomanip>
int main() {
// 编译期确定大小:6 个月
std::array<double, 6> revenue = {
188888.88, // 1月
232000.00, // 2月
166666.66, // 3月
288888.88, // 4月
356666.66, // 5月
423200.00 // 6月
};
// 使用标准算法
double total = std::accumulate(revenue.begin(), revenue.end(), 0.0);
auto [minIt, maxIt] = std::minmax_element(revenue.begin(), revenue.end());
std::cout << "=== 飞翔科技 2026 上半年营收 ===\n";
std::cout << std::fixed << std::setprecision(2);
for (size_t i = 0; i < revenue.size(); ++i)
std::cout << " " << i + 1 << "月: ¥" << revenue[i] << "\n";
std::cout << " 总营收: ¥" << total << "\n";
std::cout << " 月均: ¥" << total / revenue.size() << "\n";
std::cout << " 最低: ¥" << *minIt << " ("
<< (minIt - revenue.begin() + 1) << "月)\n";
std::cout << " 最高: ¥" << *maxIt << " ("
<< (maxIt - revenue.begin() + 1) << "月)\n";
// 零开销:sizeof(array) == sizeof(double) * 6
std::cout << "\narray 大小: " << sizeof(revenue) << " bytes ("
<< sizeof(double) * 6 << " expected)\n";
}
预期输出:
=== 飞翔科技 2026 上半年营收 ===
1月: ¥188888.88
2月: ¥232000.00
3月: ¥166666.66
4月: ¥288888.88
5月: ¥356666.66
6月: ¥423200.00
总营收: ¥1656311.08
月均: ¥276051.85
最低: ¥166666.66 (3月)
最高: ¥423200.00 (6月)
array 大小: 48 bytes (48 expected)
逐段分析:
array<double, 6>在栈上连续分配 6 × 8 = 48 字节,无额外开销.size()返回编译期常量,不占用运行时- 支持标准算法:
accumulate、minmax_element - 作为函数参数传递时不退化为指针,保持类型安全
示例二:tuple 实现多值返回
场景说明:白歌用 tuple 实现飞翔科技的数据分析函数,一次返回统计分析的三个指标。
#include <iostream>
#include <tuple>
#include <vector>
#include <string>
#include <iomanip>
// 返回三元组:平均值、中位数、标准差
std::tuple<double, double, double> analyze(const std::vector<double>& data) {
if (data.empty()) return {0, 0, 0};
// 平均值
double sum = 0;
for (auto x : data) sum += x;
double mean = sum / data.size();
// 中位数
auto sorted = data;
std::sort(sorted.begin(), sorted.end());
double median = (sorted.size() % 2 == 0)
? (sorted[sorted.size()/2 - 1] + sorted[sorted.size()/2]) / 2
: sorted[sorted.size()/2];
// 标准差
double variance = 0;
for (auto x : data) variance += (x - mean) * (x - mean);
double stddev = std::sqrt(variance / data.size());
return {mean, median, stddev};
}
int main() {
// 飞翔科技各团队月度绩效分数
std::vector<double> scores = {95, 88, 92, 78, 85, 91, 89, 94};
// C++17 结构化绑定解包
auto [avg, med, dev] = analyze(scores);
std::cout << std::fixed << std::setprecision(2);
std::cout << "=== 飞翔科技团队绩效分析 ===\n";
std::cout << "平均分: " << avg << "\n";
std::cout << "中位数: " << med << "\n";
std::cout << "标准差: " << dev << "\n";
// 传统方式:std::tie
double a, m, d;
std::tie(a, m, d) = analyze(scores);
std::cout << "\n(tie 解包) 平均分: " << a
<< ", 中位数: " << m << ", 标准差: " << d << "\n";
// 按类型获取(C++14 起)
std::tuple<std::string, int, double> employee("大翔", 28, 8888.88);
std::cout << "\n员工姓名: " << std::get<0>(employee)
<< ", 年龄: " << std::get<1>(employee)
<< ", 工资: ¥" << std::get<2>(employee) << "\n";
}
预期输出:
=== 飞翔科技团队绩效分析 ===
平均分: 89.00
中位数: 90.00
标准差: 4.90
(tie 解包) 平均分: 89.00, 中位数: 90.00, 标准差: 4.90
员工姓名: 大翔, 年龄: 28, 工资: ¥8888.88
逐段分析:
tuple作为函数返回类型,语义清晰无需定义 struct- C++17 结构化绑定
auto [avg, med, dev]是最简洁的 tuple 解包方式 std::tie是 C++11 风格的解包方式,主要用于接收已有变量std::get<Index>通过编译期索引访问元素,类型不匹配时编译报错
易错场景与面试考点
易错场景
1. array 大小是类型的一部分
std::array<int, 3> a3{1, 2, 3};
std::array<int, 5> a5{1, 2, 3, 4, 5};
// a3 = a5; // ❌ 编译错误!array<int, 3> ≠ array<int, 5>
2. tuple 的 get 使用运行期索引
std::tuple<int, double> t{1, 2.0};
int i = 2;
// std::cout << std::get<i>(t); // ❌ get 参数必须是编译期常量
3. tie 忽略某些值
double val;
std::tie(std::ignore, std::ignore, val) = std::make_tuple(1, "x", 3.14);
// 前两个值被忽略,仅提取第三个
面试考点
| 考点 | 要点 |
|---|---|
| array vs 原生数组 | array 有 size()、不退化指针、支持 swap |
| array 内存布局 | 连续内存,零额外开销(aggregate) |
| tuple 实现 | 递归继承,空基类优化(EBCO) |
| 结构化绑定 | C++17 auto [a, b, c],支持 tuple/array/struct |
| std::tie | C++11 解包方式,配合 std::ignore |
| tuple_cat | 拼接多个 tuple |
| tuple 比较 | 按字典序逐元素比较 |