avatar

目录
learncpp_16_vector

第16.1节 容器与数组入门

一、为什么需要容器?——变量可扩展性问题

1.1 问题场景

假设我们需要记录一个班级30名学生的考试成绩,并计算平均分。按照目前学过的知识,我们可能会这样做:

cpp
1
2
3
4
5
6
// 定义30个独立的整型变量
int testScore1 {};
int testScore2 {};
int testScore3 {};
// ...
int testScore30 {};

计算平均分时:

cpp
1
int average { (testScore1 + testScore2 + testScore3 + ... + testScore30) / 30 };

1.2 这种方法的问题

这种方法存在严重的可扩展性问题(scalability problem)

  1. 代码冗长:需要手动定义和操作每一个变量
  2. 容易出错:变量名容易打错,修改时容易遗漏
  3. 维护困难:如果新增一名学生,需要在整个代码中查找并修改所有相关位置
  4. 不可扩展:如果需要处理100个、1000个数据,这种方法完全不可行

思考:能否用结构体(struct)解决?

cpp
1
2
3
4
5
6
struct TestScores {
int score1 {};
int score2 {};
// ...
int score30 {};
};

虽然结构体提供了一定的组织性,但核心问题依然存在:每个成员仍需要独立的名字和独立的访问方式。


二、容器的概念

2.1 生活中的容器类比

想象你去超市买鸡蛋:

  • 你不会单独挑选12个鸡蛋放进购物车
  • 而是选择一个鸡蛋盒(carton),它包含预定数量的鸡蛋

再比如早餐麦片:

  • 麦片盒里有成百上千的麦片颗粒
  • 你不可能把每一颗麦片单独存放

容器的本质:用一个整体来管理一组相关的对象。

2.2 编程中的容器定义

容器(Container):一种数据类型,用于存储一组无名对象(unnamed objects)的集合,这些对象称为元素(elements)

关键特征

  • 容器本身有名字(如变量名)
  • 容器内的元素没有独立的名字
  • 这正是容器与结构体的本质区别

2.3 你已经使用过的容器

std::string 就是一个容器!

cpp
1
2
3
4
5
6
7
8
#include <iostream>
#include <string>

int main() {
std::string name{"Alex"}; // string是字符的容器
std::cout << name; // 输出字符序列
return 0;
}
  • 容器名:name
  • 元素:'A', 'l', 'e', 'x'(这些字符没有独立的名字)

三、容器的核心特性

3.1 元素的无名性

为什么元素不需要名字?

这是容器设计的核心理念:

  • 如果每个元素都需要名字,我们又回到了最初的问题
  • 无名性使得容器可以容纳任意数量的元素
  • 容器提供统一的访问机制来操作这些元素

重要概念

容器的元素没有独立的名字,这样容器才能容纳任意数量的元素,而不需要为每个元素指定唯一的名字。每种容器都提供特定的方法来访问其元素。

3.2 容器的长度

长度(Length)计数(Count):容器中元素的数量。

示例:

cpp
1
2
3
4
5
6
7
8
#include <iostream>
#include <string>

int main() {
std::string name{"Alex"};
std::cout << name << " has " << name.length() << " characters\n";
return 0;
}

输出:Alex has 4 characters

术语说明

  • Length(长度):元素的数量(推荐使用)
  • Size(大小):在C++中也常用来表示元素数量,但容易与内存大小混淆
  • sizeof:返回对象占用的字节数

本教程中,我们用”长度”表示元素数量,用”大小”表示内存占用。


四、容器的基本操作

回到鸡蛋盒的例子,你可以对它进行哪些操作?

  1. 获取一盒鸡蛋
  2. 打开盒子并选择一个鸡蛋
  3. 移除添加鸡蛋
  4. 计数鸡蛋数量

4.1 容器的标准操作

大多数容器支持以下操作:

操作类别 具体操作 英文术语
创建 创建空容器、指定初始容量、从列表初始化 Create/Initialize
访问 获取首元素、尾元素、任意元素 Access
修改 插入元素、删除元素 Insert/Remove
查询 获取元素数量 Query/Size

4.2 不同容器的性能差异

不同容器类型在操作性能上有显著差异:

  • 容器A:快速访问任意元素,但不支持插入/删除
  • 容器B:快速插入/删除,但只能顺序访问元素

选择合适的容器类型对代码的可维护性和性能至关重要。


五、元素类型

5.1 同质性容器

在大多数编程语言(包括C++)中,容器是同质的(homogeneous)

  • 容器内所有元素必须是相同类型
  • 例如:整数容器只能存储整数,字符串容器只能存储字符串

5.2 C++中的类型灵活性

C++容器通常实现为类模板(class template)

cpp
1
2
3
std::vector<int>     intVector;     // 整数容器
std::vector<double> doubleVector; // 浮点数容器
std::vector<string> stringVector; // 字符串容器

优势

  • 不需要为每种元素类型创建新的容器类
  • 通过模板类型参数(template type argument)指定元素类型
  • 一次实现,多种类型复用

5.3 异质性容器

异质容器(heterogeneous container):允许不同类型的元素。

  • 常见于脚本语言(如Python)
  • C++标准库不直接支持(但可通过高级技术实现)

六、C++中的容器库

6.1 容器库概述

容器库(Containers Library):C++标准库的一部分,包含多种实现常见容器的类类型。

容器类(Container Class):实现容器功能的类类型。

完整列表参见:cppreference - Containers

6.2 C++容器的严格定义

注意:C++对”容器”的定义比通用编程定义更严格。

以下类型不是C++标准意义上的容器:

  • C风格数组(C-style arrays)
  • std::string
  • std::vector<bool>

原因:它们未实现容器的所有必需接口(详见容器要求)。

std::stringstd::vector<bool> 实现了大部分要求,因此被称为伪容器(pseudo-containers)

6.3 最常用的容器

在所有容器类中,std::vectorstd::array 使用最广泛,是本课程的重点。


七、数组简介

7.1 数组的定义

数组(Array):一种容器数据类型,以连续方式(contiguously)存储一系列值。

连续存储:每个元素放置在相邻的内存位置,没有间隙。

数组的优势

  • 快速、直接访问任意元素
  • 概念简单,易于使用
  • 处理相关值集合的首选方案

7.2 C++中的三种数组类型

数组类型 引入时间 特点 别名
C风格数组 继承自C语言 核心语言特性,行为怪异,不安全 C arrays, naked arrays, built-in arrays
std::vector C++03 最灵活,功能丰富,动态大小 动态数组
std::array C++11 替代C风格数组,固定大小,更安全高效 固定数组

7.3 各类型数组的应用场景

  1. C风格数组

    • 遗留代码维护
    • 与C库交互
    • 现代C++中应避免使用
  2. std::vector

    • 元素数量动态变化
    • 需要频繁插入/删除
    • 最常用的数组类型
  3. std::array

    • 元素数量固定
    • 追求最高性能
    • 小型数组

八、学习路线

8.1 下一步学习内容

下一节课我们将:

  1. 深入学习 std::vector
  2. 解决本节开头提出的30名学生成绩问题
  3. 引入相关的新概念
  4. 解决实际应用中的挑战

8.2 学习策略

好消息:所有容器类具有相似的接口

  • 学会一个容器(如 std::vector),其他容器(如 std::array)就容易多了
  • 后续学习其他容器时,我们将重点关注差异点重要特性

8.3 术语约定

本教程中:

  • 容器类(container classes):指标准库中的大多数或所有容器类
  • 数组(array):泛指所有数组类型,包括其他编程语言中的数组

std::vector 同时属于这两个类别,因此即使使用不同术语,也适用于 std::vector


九、本节小结

核心概念回顾

  1. 容器:存储无名元素集合的数据类型
  2. 元素无名性:容器可扩展性的关键
  3. 同质性:C++容器要求元素类型一致
  4. 数组:连续存储的容器,支持快速访问
  5. 三种数组:C风格数组、std::vectorstd::array

关键英文术语

  • Container(容器)
  • Element(元素)
  • Length/Count(长度/计数)
  • Homogeneous(同质的)
  • Contiguously(连续地)
  • Container Class(容器类)
  • C-style Array(C风格数组)

准备好了吗?让我们开始深入学习 std::vector 🚀


评论