乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • C++ 学习路径
  • 第1章 C++概述与开发环境

    • C++ 语言概述与编译模型
    • 第一个 C++ 程序与规范
    • 开发环境配置
    • 预处理指令详解
  • 第2章 基本语法与类型系统

    • 变量与基本类型
    • 类型转换
    • 枚举类型
    • 引用与指针
    • 数组与 stdarray
    • 字符串与原始字符串字面量
    • const 与 constexpr
    • nullptr 与空指针
    • 类型推导 auto 与 decltype
    • 基于范围的 for 循环
    • 值类别全面解析
    • char16_t 与 char32_t
    • static_assert 编译期断言
  • 第3章 函数与重载

    • 函数声明与定义
    • 函数重载
    • 默认参数与内联函数
    • Lambda 表达式
    • 函数对象与 stdfunction
    • 后置返回类型与 noexcept
  • 第4章 类与对象

    • 类的基本定义
    • 构造函数与析构函数
    • 拷贝控制
    • 移动构造函数与移动赋值
    • 列表初始化与类内初始化器
    • 静态成员与嵌套类
    • 友元
    • =default 与 =delete
  • 第5章 继承与多态

    • 继承基础
    • 虚函数与多态
    • 虚函数表与动态绑定原理
    • 虚析构函数
    • 抽象类与纯虚函数
    • 多重继承与虚继承
    • 继承构造函数
  • 第6章 运算符重载

    • 运算符重载基础
    • 算术与关系运算符重载
    • 赋值与移动运算符重载
    • 特殊运算符重载
  • 第7章 模板与泛型编程

    • 函数模板
    • 类模板
    • 模板特化与偏特化
    • 可变参数模板
    • 别名模板与模板模板参数
    • SFINAE 与类型萃取
    • 依赖名与 typename/template 关键字
  • 第8章 异常处理

    • 异常处理机制
    • noexcept 与异常安全
    • RAII 与异常安全实践
  • 第9章 内存管理与智能指针

    • 动态内存与内存分区
    • RAII 惯用法
    • unique_ptr
    • shared_ptr 与 weak_ptr
    • 内存管理最佳实践
  • 第10章 右值引用与移动语义

    • 右值引用与值类别深度解析
    • std::move 原理与使用
    • 完美转发与 std::forward
    • 移动语义性能对比与最佳实践
  • 第11章 STL容器

    • vector 深度剖析
    • deque 内部机制
    • list 与 forward_list
    • map 与 set 深度解析
    • unordered 容器与哈希原理
    • array 与 tuple
    • 容器适配器
    • 容器选择全景指南
  • 第12章 STL算法与迭代器

    • 迭代器体系全解
    • 非变异算法
    • 变异算法
    • 排序与二分算法
    • Lambda 与算法组合
    • std::random 随机数库
    • 自定义迭代器开发
  • 第13章 IO流与文件

    • 标准 IO 流
    • 格式化输出控制
    • 文件流操作
    • 字符串流
    • std::regex 正则表达式
  • 第14章 并发与多线程

    • thread 基础与线程管理
    • mutex 与 lock_guard
    • unique_lock 与 condition_variable
    • thread_local 线程局部存储
    • atomic 与内存序
    • future 与 async 异步编程
    • std::chrono 时间库
  • 第15章 现代C++新特性

    • 从 C++11 到 C++20 演进路线
    • C++14 关键新特性
    • C++17 关键新特性
    • C++20 核心特性速览
  • 第16章 面试考点与最佳实践

    • C++ 综合最佳实践清单
    • 高频面试题精讲
    • 多线程面试题与实战
    • 内存管理常见陷阱与排查
  • 附录

    • C++ 核心知识点
    • C++ 专业术语

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);
特性arraytuple
元素类型同构异构(任意组合)
大小编译期确定编译期确定
内存栈上连续栈上聚合
访问[] / 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::tieC++11 解包方式,配合 std::ignore
tuple_cat拼接多个 tuple
tuple 比较按字典序逐元素比较
上一页
unordered 容器与哈希原理
下一页
容器适配器