跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 零基础入门教程:现代 C++ 核心武器库 STL

掌握 C++ STL 标准模板库基础应用,包括 std::vector 动态数组、std::string 字符串处理及 std::map 键值对容器。通过重构成绩系统与实现控制台通讯录项目,演示利用 STL 替代手动内存管理,提升代码安全性与效率。内容涵盖常用操作示例、类型安全说明及性能优化建议,帮助开发者从 C 风格迈向现代 C++。

草莓泡芙发布于 2026/2/22更新于 2026/10/2486 浏览
C++ 零基础入门教程:现代 C++ 核心武器库 STL

C++ 零基础入门教程(第 4 篇)

STL 标准库实战 —— 告别手动内存管理

第一步:为什么需要 STL?

回顾之前的代码,我们用了固定大小的数组:

Student students[10]; // 最多 10 人

但现实中,学生数量是不确定的。如果用 new[] 动态分配,又容易忘记 delete[],导致内存泄漏。

✅ STL 的优势:
  • 自动管理内存(无需 new/delete)
  • 动态扩容(如 vector)
  • 提供丰富算法(排序、查找等)
  • 类型安全、异常安全

第二步:std::vector —— 动态数组(必学!)

vector 是可变长数组,会自动增长。

2.1 基本用法
#include <iostream>
#include <vector>
// 必须包含
using namespace std;

int main() {
    // 创建空 vector
    vector<int> numbers;
    
    // 添加元素(自动扩容)
    numbers.push_back(10);
    numbers.push_back(20);
    numbers.push_back(30);
    
    // 访问元素(和数组一样)
    cout << "第一个数:" << numbers[0] << endl;
    cout << "最后一个数:" << numbers.back() << endl;
    
    // 获取大小
    cout << "当前有 " << numbers.size() << " 个元素" << endl;
    
    // 遍历(C++11 范围 for 循环)
    for (int x : numbers) {
        cout << x << " ";
    }
    cout << endl;
    return 0;
}

✅ 输出:

第一个数:10 最后一个数:30 当前有 3 个元素 10 20 30

🔑 常用操作:.push_back(value) → 末尾添加 .pop_back() → 删除末尾 .size() → 元素个数 .empty() → 是否为空 [index] 或 .at(index) → 访问(.at 会检查越界)


2.2 vector 存储自定义类型(如 Student)
#include <vector>
#include <string>
using namespace std;

class Student {
public:
    string name;
    double score;
    Student(string n, double s) : name(n), score(s) {}
};

int main() {
    vector<Student> students;
    students.push_back(Student("Alice", 95));
    students.push_back(Student("Bob", 88));
    
    for (const Student& s : students) {
        // 用引用避免拷贝
        cout << s.name << ": " << s.score << endl;
    }
    return 0;
}

💡 注意:const Student& 避免不必要的对象复制,提升性能!


第三步:std::string —— 真正的字符串类型

你可能还记得 C 风格字符串(char[])的麻烦:

  • 手动管理长度
  • 容易缓冲区溢出
  • 拼接、查找很复杂
✅ std::string 的强大功能:
#include <iostream>
#include <string>
using namespace std;

int main() {
    string name = "Hello";
    name += " C++"; // 拼接
    cout << name << endl; // Hello C++
    cout << "长度:" << name.length() << endl; // 8
    
    if (name.find("C++") != string::npos) {
        cout << "包含 'C++'" << endl;
    }
    
    // 遍历每个字符
    for (char c : name) {
        cout << c << "-";
    }
    cout << endl;
    return 0;
}

✅ 输出:

Hello C++ 长度:8 包含 'C++' H-e-l-l-o- -C-+-+-

🎯 结论:永远优先使用 std::string,不要用 char[]!


第四步:std::map —— 键值对容器(类似 Java HashMap)

map 用于存储 键 → 值 的映射,自动按键排序。

示例:用 map 统计单词出现次数
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> wordCount;
    wordCount["apple"] = 5;
    wordCount["banana"] = 3;
    wordCount["apple"]++; // 变成 6
    
    // 遍历 map
    for (const auto& pair : wordCount) {
        cout << pair.first << ": " << pair.second << endl;
    }
    
    // 查找
    if (wordCount.count("orange")) {
        cout << "有 orange" << endl;
    } else {
        cout << "没有 orange" << endl;
    }
    return 0;
}

✅ 输出:

apple: 6 banana: 3 没有 orange

🔑 说明:pair.first 是键,pair.second 是值 auto 让编译器自动推导类型(C++11 特性) .count(key) 返回 0 或 1(是否存在)


第五步:升级项目 1 —— 用 vector 重构成绩系统

我们将移除 MAX 限制,支持任意数量学生。

✅ 改造 GradeSystem 类:
// grade_system_stl.cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Student {
private:
    string name;
    double score;
public:
    Student(string n, double s) : name(n), score(s) {}
    string getName() const { return name; }
    double getScore() const { return score; }
    void print() const { cout << name << "\t" << score << endl; }
};

class GradeSystem {
private:
    vector<Student> students; // ← 关键:用 vector 替代数组
public:
    void addStudent(const string& name, double score) {
        students.push_back(Student(name, score)); // 自动扩容
    }
    
    void printAll() const {
        cout << "\n--- 成绩列表 ---\n";
        for (const auto& s : students) {
            s.print();
        }
    }
    
    double getAverage() const {
        if (students.empty()) return 0;
        double sum = 0;
        for (const auto& s : students) {
            sum += s.getScore();
        }
        return sum / students.size();
    }
    
    Student getTopStudent() const {
        if (students.empty()) return Student("无", 0);
        Student top = students[0];
        for (const auto& s : students) {
            if (s.getScore() > top.getScore()) {
                top = s;
            }
        }
        return top;
    }
};

int main() {
    GradeSystem sys;
    sys.addStudent("Alice", 95);
    sys.addStudent("Bob", 88);
    sys.addStudent("Charlie", 92);
    sys.addStudent("David", 97); // 可以无限加!
    
    sys.printAll();
    cout << "\n平均分:" << sys.getAverage() << endl;
    cout << "最高分:";
    sys.getTopStudent().print();
    return 0;
}

✅ 编译运行:

g++ grade_system_stl.cpp -o grade ./grade

🎉 现在系统可以处理任意数量学生,且内存自动管理!


第六步:实战项目 2 —— 控制台通讯录

我们将综合使用 vector + string + map(可选),实现:

  • 添加联系人(姓名 + 电话)
  • 查找联系人
  • 列出所有联系人
✅ 方案选择:
  • 用 vector<Contact> 存储(适合遍历)
  • 或用 map<string, string>(姓名 → 电话,适合快速查找)

我们采用 vector + 线性查找(简单清晰):

// contact_book.cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Contact {
public:
    string name;
    string phone;
    Contact(string n, string p) : name(n), phone(p) {}
};

class ContactBook {
private:
    vector<Contact> contacts;
public:
    void addContact(const string& name, const string& phone) {
        contacts.push_back(Contact(name, phone));
        cout << "已添加 " << name << endl;
    }
    
    void findContact(const string& name) const {
        bool found = false;
        for (const auto& c : contacts) {
            if (c.name == name) {
                cout << "找到:" << c.name << " - " << c.phone << endl;
                found = true;
            }
        }
        if (!found) {
            cout << "未找到 " << name << endl;
        }
    }
    
    void listAll() const {
        if (contacts.empty()) {
            cout << "通讯录为空" << endl;
            return;
        }
        cout << "\n--- 通讯录 ---\n";
        for (const auto& c : contacts) {
            cout << c.name << "\t" << c.phone << endl;
        }
    }
};

int main() {
    ContactBook book;
    int choice;
    string name, phone;
    while (true) {
        cout << "\n1. 添加联系人\n2. 查找联系人\n3. 列出所有\n0. 退出\n请选择:";
        cin >> choice;
        if (choice == 0) break;
        switch (choice) {
            case 1:
                cout << "姓名:";
                cin >> name;
                cout << "电话:";
                cin >> phone;
                book.addContact(name, phone);
                break;
            case 2:
                cout << "查找姓名:";
                cin >> name;
                book.findContact(name);
                break;
            case 3:
                book.listAll();
                break;
            default:
                cout << "无效选项" << endl;
        }
    }
    cout << "再见!" << endl;
    return 0;
}

✅ 编译运行:

g++ contact_book.cpp -o contact ./contact

🎮 你可以添加、查找、列出联系人,完全由 STL 驱动!


📌 本篇小结:你已掌握

容器用途对比 Java
vector<T>动态数组≈ ArrayList<T>
string字符串≈ String(但更高效)
map<K,V>有序键值对≈ TreeMap<K,V>

✅ 你已具备:使用 STL 编写安全、高效的 C++ 代码。用 vector 替代原始数组构建小型数据管理系统。


✅ 下一步建议

  1. 尝试优化通讯录:用 map<string, string> 实现 O(log n) 查找
  2. 预习:什么是'智能指针'?如何管理堆对象?
  3. 思考:如果 Contact 很大,如何避免 push_back 时的拷贝开销? → 答案:移动语义(第 5 篇)

目录

  1. C++ 零基础入门教程(第 4 篇)
  2. STL 标准库实战 —— 告别手动内存管理
  3. 第一步:为什么需要 STL?
  4. ✅ STL 的优势:
  5. 第二步:std::vector —— 动态数组(必学!)
  6. 2.1 基本用法
  7. 2.2 vector 存储自定义类型(如 Student)
  8. 第三步:std::string —— 真正的字符串类型
  9. ✅ std::string 的强大功能:
  10. 第四步:std::map —— 键值对容器(类似 Java HashMap)
  11. 示例:用 map 统计单词出现次数
  12. 第五步:升级项目 1 —— 用 vector 重构成绩系统
  13. ✅ 改造 GradeSystem 类:
  14. 第六步:实战项目 2 —— 控制台通讯录
  15. ✅ 方案选择:
  16. 📌 本篇小结:你已掌握
  17. ✅ 下一步建议

更多推荐文章

查看全部
  • Vue 组件切换实战:动态组件与 Tab 切换实现
  • Stack-Chan 机器人入门与开发实战
  • Linux 进程信号的产生机制详解
  • Altera USB-Blaster 驱动安装与 FPGA 下载调试指南
  • 智慧养老手表管理系统前端样式层功能说明
  • DeepSeek R1 个人 AI 知识库搭建指南(API 与本地部署)
  • Whisper.cpp 量化模型清单及 ggml 格式下载指南
  • 机器学习经典算法:深入解析决策树原理与实现
  • SKResNet 架构详解:融合选择性卷积与残差结构
  • Java volatile 关键字:底层原理、应用场景与最佳实践
  • Java 泛型与通配符:从原理到实战
  • 大模型商业化能力成竞争关键:百度文心实践分析
  • Gitea 本地部署指南:安装配置与常用 Git 命令实战
  • 数据结构复习:Java 顺序表与 ArrayList 详解
  • 开源 AI 助手 Molt Bot 国内 Docker 部署指南
  • 企业级 Nginx 高性能部署与优化实战
  • 异步定时任务系统设计与 Rust 实战集成
  • Linux 网络基础:TCP/IP 协议栈与分层模型解析
  • S95×S88×UNS 智能制造架构设计:以可交付机制为核心
  • 前端防录屏原理:EME DRM 机制解析与实战代码

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online