C++ 容器

C++ 容器(Containers)详解

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


一、什么是容器?

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

容器的核心特征:

  • 存储多个同类型元素 (如 int、string、自定义对象等);
  • 自动管理内存 (无需手动 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)
大小动态调整 ❌ 固定大小 ✅ vector、string 等可自动扩容
安全性 低(无边界检查) 高(.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::vector 和 std::string 是最常用的容器;
  • 选择容器的原则:
  • 需要随机访问?→ vector
  • 频繁中间插入?→ list
  • 快速按键查找?→ unordered_map
  • 只需栈/队列行为?→ stack / queue
  • 结合 auto、范围 for、STL 算法,写出简洁安全的代码!

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

相关推荐
BaiPeter42 分钟前
ZPL文件预览
开发语言·c++
悠仁さん3 小时前
【C++】哈希表
c++·算法·散列表
Severus_black5 小时前
【C++初阶】list使用及相关实现,思路顺滑流畅!
c语言·数据结构·c++·stl·list
噢,我明白了6 小时前
JAVA中的一些基础应用知识点
java·开发语言
时间的拾荒人7 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾7 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
码途行者8 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
旖旎夜光9 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
你看我名字9 小时前
产品参数昨天还对,今天已过期:数眼智能与大模型应用如何做资料版本校验
开发语言·架构
老秦包你会10 小时前
计算机网络第二课 ----Socket(套接字)编程预备
开发语言·计算机网络·php