C++ 容器

C++ 容器(Containers)详解

在 C++ 标准库(STL, Standard Template Library)中,容器(Container) 是用于存储和管理一组对象的核心组件。它们封装了数据结构与常用操作,使开发者无需手动管理内存或实现底层算法,从而写出更安全、简洁、高效的代码。所有标准容器都是类模板(class templates)!


一、什么是容器?

容器是 C++ 标准库提供的、通用的类模板(class templates),用于组织和操作一组元素。

容器的核心特征:

  • 存储多个同类型元素 (如 intstring、自定义对象等);
  • 自动管理内存 (无需手动 new/delete);
  • 提供统一接口 :如 .size().empty().begin().end()
  • 支持迭代器遍历STL 算法 (如 std::sort, std::find);
  • 类型安全:编译期检查,避免越界(部分容器)。

注意:容器是 标准库预定义的类,不是用户"自定义类"------你使用它们,而不是从零实现它们。


二、容器的分类

C++ 标准将容器分为三大类:

1. 序列容器(Sequence Containers)

元素按线性顺序存储,位置由插入顺序决定。

容器 特点 典型用途
std::vector 动态数组,支持随机访问,尾部插入快 通用首选,替代 C 数组
std::deque 双端队列,首尾插入/删除快 需要双向高效操作
std::list 双向链表,任意位置插入/删除快 频繁中间插入/删除
std::forward_list 单向链表,内存开销最小 内存敏感场景
std::array 固定大小数组(编译期确定) 替代 C 风格数组,更安全
std::string 特化的字符序列容器 存储和操作文本

std::string 虽然用于文本,但技术上属于序列容器!


2. 关联容器(Associative Containers)

基于红黑树 实现,元素按键自动排序,查找效率为 O(log n)

容器 键是否唯一 是否有序 元素类型
std::set 唯一 Key
std::multiset 允许重复 Key
std::map 唯一 pair<const Key, Value>
std::multimap 允许重复 pair<const Key, Value>

🔒 map 的键(first)是 const,不可修改!


3. 无序关联容器(Unordered Associative Containers)

基于哈希表 实现,元素无序,平均查找效率为 O(1)

容器 键是否唯一 是否有序
std::unordered_set 唯一
std::unordered_multiset 允许重复
std::unordered_map 唯一
std::unordered_multimap 允许重复

⚡ 适合需要快速查找且不关心顺序的场景。


4. 容器适配器(Container Adapters)

基于其他容器封装,限制接口以提供特定行为。

适配器 默认底层容器 行为
std::stack deque 后进先出(LIFO)
std::queue deque 先进先出(FIFO)
std::priority_queue vector 按优先级出队(最大堆)

🛠️ 适配器不支持迭代器,不能遍历!


三、为什么使用容器? vs C 风格数组

对比项 C 风格数组 / 指针 C++ 容器
内存管理 手动(易泄漏、越界) 自动(RAII)
大小动态调整 ❌ 固定大小 vectorstring 等可自动扩容
安全性 低(无边界检查) 高(.at() 有检查,迭代器安全)
功能 仅存储 内置丰富操作(push_back, find, sort 等)
泛型支持 ✅ 模板 + STL 算法

🚫 示例:C 风格危险代码

c 复制代码
char buf[5];
strcpy(buf, "Hello!"); // 缓冲区溢出!

✅ C++ 安全替代

cpp 复制代码
std::string s = "Hello!"; // 自动分配 7 字节,安全!

四、容器的通用操作示例

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

int main() {
    // 1. 创建容器
    std::vector<int> vec = {3, 1, 4, 1, 5};

    // 2. 遍历(三种方式)
    for (size_t i = 0; i < vec.size(); ++i)        // 索引
        std::cout << vec[i] << " ";
    
    for (auto it = vec.begin(); it != vec.end(); ++it) // 迭代器
        std::cout << *it << " ";
    
    for (const auto& x : vec)                       // 范围 for
        std::cout << x << " ";

    // 3. 使用 STL 算法
    std::sort(vec.begin(), vec.end()); // 排序
    auto pos = std::find(vec.begin(), vec.end(), 4); // 查找

    // 4. string 作为容器
    std::string s = "hello";
    std::reverse(s.begin(), s.end()); // → "olleh"

    return 0;
}

五、常见误区澄清

误区 正确理解
"容器是自己写的类" ❌ 容器是 标准库提供的类模板
"所有类都是容器" ❌ 只有满足容器要求的类才是(如提供 begin()/end()
"string 不是容器" std::string标准序列容器
"容器一定防止越界" ⚠️ operator[] 不检查,.at() 才抛异常

六、总结

  • 容器是 C++ 现代编程的基石,应优先于 C 风格数组和指针;
  • std::vectorstd::string 是最常用的容器
  • 选择容器的原则
  • 需要随机访问?→ vector
  • 频繁中间插入?→ list
  • 快速按键查找?→ unordered_map
  • 只需栈/队列行为?→ stack / queue
  • 结合 auto、范围 for、STL 算法,写出简洁安全的代码!

记住:在 C++ 中,能用标准容器,就不要手写数组或链表!

相关推荐
你的代码我的心2 小时前
微信开发者工具开发网页,不支持tailwindcss v4怎么办?
开发语言·javascript·ecmascript
瑞雪兆丰年兮2 小时前
[从0开始学Java|第十二天]学生管理系统升级
java·开发语言
弹简特2 小时前
【JavaSE-网络部分03】网络原理-泛泛介绍各个层次
java·开发语言·网络
执风挽^2 小时前
Python_func_basic
开发语言·python·算法·visual studio code
怪谈爱好者CMZ2 小时前
【C++学习笔记】图论-最短路径Dijkstra算法
c++·笔记·学习
tangchao340勤奋的老年?2 小时前
ADS通信 C++ 设置通知方式读取指定变量
开发语言·c++·算法
froginwe112 小时前
SOAP 简介
开发语言
xuchaoxin13752 小时前
bash@特殊字符@环境变量符号@特殊参数@参数扩展和替换@字符串处理用法总结
开发语言·bash
devmoon2 小时前
快速了解兼容 Ethereum 的 JSON-RPC 接口
开发语言·网络·rpc·json·区块链·智能合约·polkadot