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++ 中,能用标准容器,就不要手写数组或链表!

相关推荐
初阳7855 分钟前
【Qt】界面优化(1)——QSS
开发语言·qt
影寂ldy19 分钟前
C# WinForms 窗体继承
开发语言·c#
小白学大数据21 分钟前
无库无捷径,PyTorch 手写完整 Transformer 大语言模型 LLM
开发语言·pytorch·语言模型·transformer
阿pin21 分钟前
Java随笔-JVM内存模型
java·开发语言·jvm·内存模型
虚心的百褶裙1 小时前
JavaScript性能优化
开发语言·javascript·性能优化
凯瑟琳.奥古斯特1 小时前
二分查找解力扣1011最优运载能力
开发语言·c++·算法·leetcode·职场和发展
WZF-Sang1 小时前
TCP和UDP协议
linux·服务器·网络·c++·学习·tcp/ip·udp
Tim_101 小时前
【C++】014、左值与右值的区别
开发语言·c++
想人陪的玫瑰1 小时前
winform 能用 Native AOT 吗?——TDS 项目的实战尝试
c++·mfc
天空'之城1 小时前
Linux 系统编程 14:Reactor 反应堆模式
linux·开发语言·网络编程·reactor 反应堆模式