C++启蒙课程:第16章  string类和标准模板库

我们将迎来“超级宝库”——STL!掌握 `string`、`vector`、智能指针和算法,用最少的代码完成最复杂的任务!

🎗️

魔法绳索与弹性数组

掌握“自动伸缩的魔法绳” `string` 和“超级弹性数组” `vector`。

🤵

内存保镖与数据导航

认识“内存的智能保镖” `unique_ptr` 和“数据GPS” `iterator`。

🤖

通用指令与函数魔术师

学会“可携带的函数机器人” `Functor` 和“万能操作指令” `algorithm`。

课时一:魔法绳索与弹性数组

(覆盖知识点 16.1, 16.3, 16.7)

16.1.2 “魔法绳索” (string I/O)

`cin` 机器人遇到空格就停下。`getline()` 机器人能把“魔法绳”拉长,装下整行。

#include <string> string s; // 16.1.2 读取一整行 (魔法绳) getline(cin, s); // 16.1.1 构造 string s1 = "hello"; string s2(s1);

16.3 “超级弹性数组” (vector)

`vector` 是“弹性数组”。你不需要预先知道大小,用 push_back() 就能自动“伸长”装下新数据。

Vector (Size: 0):
#include <vector> // 16.3.1 声明 vector scores; // 16.3.2 动态添加 scores.push_back(99); scores.push_back(100); // 16.7.2 C++11 初始化 vector v = {1, 2, 3};

课时二:内存保镖与数据导航

(覆盖知识点 16.2, 16.4)

16.2 “内存的智能保镖”

`unique_ptr` 是“智能保镖”,它拥有数据的“独家契约”。所有权必须用 std::move 转移,原指针失效。

ptr1
ptr2
🤵 Data
#include <memory> // 16.2.3 智能保镖 unique_ptr ptr1(new int(100)); // ptr2 = ptr1; // 错误!禁止复制 // 16.2.3 必须转移所有权 (独家契约) unique_ptr ptr2 = std::move(ptr1); // ptr1 自动变为 nullptr (失效) // ptr2 拥有内存 // main 结束时, ptr2 自动 delete

16.4 “数据探险家的GPS”

迭代器 (it) 就像一个GPS。++it 是“移动到下一个位置”,*it 是“读取当前位置的数据”。

vector v = {10, 20, 30}
📍
10 20 30
vector v = {10, 20, 30}; // 16.4.1 迭代器 (GPS) vector::iterator it; // 指向第一个位置 it = v.begin(); // 移动到下一个位置 ++it; // 读取当前位置 (20) cout << *it;

课时三:通用指令与函数魔术师

(覆盖知识点 16.5, 16.6)

16.5 “可携带的函数机器人”

函数对象 (Functor) 是一个重载了 () 的对象。它像一个机器人,既能执行指令 (()),还能携带“状态”(成员变量)。

机器人 🤖 (Total: 0)
// 16.5.1 函数机器人 class Adder { private: int total; // 携带的状态 public: Adder(int t = 0) : total(t) {} // 重载 () 运算符 void operator()(int n) { total += n; cout << "New Total: " << total; } }; // Adder robot; // robot(10); // 像函数一样调用

16.6 “万能操作指令” (算法)

STL 算法 (如 std::sort) 是“万能指令”。它们不关心容器,只关心你用“GPS” (迭代器) 告诉它的起止点。

vector scores = {95, 88, 100, 75}
#include <algorithm> #include <functional> vector scores = {95, 88, 100}; // 16.6 算法 sort(scores.begin(), scores.end()); // 16.5.2 使用函数符 sort(scores.begin(), scores.end(), greater());

编程实践与作业

是时候检验你作为“STL效率大师”的实力了!

练习 1:字符串与弹性数组 (16.1, 16.3)

任务:

编写程序,要求用户输入5个水果的名称(使用 string,可包含空格),将它们存储在一个 vector 中。然后使用基于范围的 for 循环打印出所有名称。

点击查看参考答案
#include <iostream> #include <string> #include <vector> using namespace std; int main() { vector fruits; // 16.3.1 声明 string fruit_name; for (int i = 0; i < 5; ++i) { cout << "第 " << i + 1 << " 个: "; getline(cin, fruit_name); // 16.1.2 fruits.push_back(fruit_name); // 16.3.2 } cout << "\n你输入的水果是:" << endl; // 16.3.4 基于范围的 for for (const string & name : fruits) { cout << " - " << name << endl; } return 0; }
练习 2:内存保镖 (unique_ptr) (16.2)

任务:

编写一个程序,演示如何使用 unique_ptr 分配一个动态整数,并使用 std::move 将其所有权转移给另一个指针。

点击查看参考答案
#include <iostream> #include <memory> // 引入智能指针 #include <utility> // 用于 std::move using namespace std; int main() { // 16.2.1 守护动态内存 unique_ptr ptr1(new int(100)); unique_ptr ptr2; // 16.2.3 必须使用 std::move 转移所有权 ptr2 = std::move(ptr1); cout << "ptr2 守护的值: " << *ptr2 << endl; if (ptr1 == nullptr) { cout << "ptr1 已经失效。" << endl; } // ptr2 结束时自动 delete return 0; }
练习 3:万能指令 (STL 算法) (16.6)

任务:

编写一个程序,使用 vector 存储一组分数。然后使用 std::sort 算法和 greater 函数符对分数进行**降序**排序。

点击查看参考答案
#include <iostream> #include <vector> #include <algorithm> // 16.6 算法库 #include <functional> // 16.5.2 函数符库 using namespace std; int main() { vector scores = {95, 88, 100, 75, 99}; // 16.6.2 使用迭代器区间 // 16.5.2 使用预定义函数符 sort(scores.begin(), scores.end(), greater()); cout << "降序排序后: "; for (int s : scores) cout << s << " "; cout << endl; return 0; }

本章知识点总结与复习

核心概念 解释/功能 关键用法/示例
string 类“魔法绳索”,自动管理大小和内存。string s; getline(cin, s);
vector 模板类“超级弹性数组”,可在运行时动态调整大小。vector v; v.push_back(item);
智能指针“内存保镖”,在对象过期时自动 `delete`。unique_ptr p(new T);
`unique_ptr`独占所有权,必须用 `std::move` 转移。p2 = std::move(p1);
迭代器“数据GPS”,访问容器元素的通用指针。v.begin(), *it, ++it
函数对象 (Functor)重载了 `operator()` 的类对象,可携带状态。class Adder { ... };
STL 算法“万能指令”,不依赖容器,操作迭代器区间。std::sort(begin, end);