【数据结构】stl 容器

序列容器(顺序存储元素)

关联容器(基于键值存储,允许快速查找)

有序关联容器‌(元素按键排序):

无序关联容器‌(C++11引入,基于哈希表):

容器适配器(基于其他容器封装)

其他容器




std::vector 数据结构与内存管理

1. 底层结构
  • 连续内存块‌:元素在内存中紧密排列
  • 三指针逻辑‌(典型实现):
    • begin_ptr → 内存起始位置
    • size_ptr → 当前元素末尾(size()
    • capacity_ptr → 内存块末尾(capacity()

2. 插入操作
场景操作步骤时间复杂度
尾部空间充足1. 在size_ptr处构造元素
2. size_ptr后移
O(1)
空间不足需扩容1. 分配新内存(容量:GCC×2 / MSVC×1.5)
2. 迁移数据(优先移动语义)
3. 释放旧内存
均摊 O(1)
中间插入1. 移动后续元素腾出空间
2. 构造新元素
O(n)

3. 删除操作
类型操作步骤时间复杂度
尾部删除1. 销毁末尾元素
2. size_ptr前移
O(1)
中间删除1. 销毁目标元素
2. 向前移动后续元素覆盖空隙
O(n)

4. 关键特性
  • 内存策略‌:
    • 扩容:指数增长(避免频繁重分配)
    • 不自动缩容:erase不释放内存
  • 迭代器失效‌:
    • 扩容或中间插入/删除导致迭代器失效

性能对比‌:

操作复杂度适用性
随机访问O(1)★★★★★
尾部操作均摊 O(1)★★★★★
中间操作O(n)★☆☆☆☆

手动释放:

v.shrink_to_fit();// 请求释放多余内存vector<int>().swap(v);// 强制释放所有内存


std::deque 核心知识点总结

一、基础概念与特性
  1. 容器类型
    C++ STL 中的‌双端队列‌(double-ended queue)
  2. 访问特性
    支持‌随机访问‌(通过 operator[]at()
  3. 动态扩展
    两端插入/删除操作高效,时间复杂度为 ‌O(1)
  4. 底层实现
    基于‌分段连续存储‌结构(多个固定大小的数组块 + 中央控制块)

二、内存管理机制
特性说明
默认分配器std::allocator<T>
分段存储结构由多个‌固定大小的数组块‌组成(典型块大小 512 bytes - 4KB)
中央控制映射器维护指向所有块的指针数组(动态扩容时重新分配)
内存分配策略插入时:
- 两端:直接使用预留空间或分配新块
- 中间:移动元素
扩容机制中央指针数组满时重新分配(通常翻倍)
非连续内存元素物理存储非连续,但逻辑连续
内存布局示例‌:

三、核心操作特性
操作时间复杂度说明
头尾插入/删除O(1)push_front()/pop_front()
push_back()/pop_back()
随机访问O(1)operator[]at() 直接访问元素
中间插入/删除O(n)insert()/erase() 需移动元素
迭代器操作O(1)支持随机访问迭代器(++, --, +n 等)

四、模板参数
template<classT,// 元素类型classAllocator= std::allocator<T>// 分配器类型>classdeque;


std::list 核心知识点总结

一、基础概念与特性
  1. 容器类型
    C++ STL 中的‌双向链表‌容器
  2. 存储结构
    每个元素存储在独立的节点中,节点包含:
    • 数据值
    • 前驱节点指针
    • 后继节点指针
  3. 迭代器特性
    支持‌双向迭代器‌(可前向/后向遍历)

二、内存管理机制
特性说明
默认分配器std::allocator<T>
节点内存分配每个元素独立分配内存(包含数据+两个指针)
分配触发时机push_back/push_front/insert 时分配新节点
内存释放时机pop_back/pop_front/erase 时立即释放节点
内存碎片高频插入删除可能产生内存碎片
连续内存❌ 元素在内存中‌非连续存储
节点结构示例‌:

三、核心操作特性
操作时间复杂度说明
头尾插入/删除O(1)push_front()/pop_front()
push_back()/pop_back()
任意位置插入O(1)insert(iterator_pos, value)(只需修改相邻节点指针)
任意位置删除O(1)erase(iterator_pos)(只需修改相邻节点指针)
元素查找O(n)必须从头/尾开始遍历
迭代器稳定性✅ 稳定插入/删除操作‌不会使其他迭代器失效‌(除被删除元素的迭代器)

四、特殊成员函数
  1. 链表拼接
    splice():将其他链表的元素移动到当前链表(O(1)时间复杂度)
    // 将other链表的全部元素移动到当前链表末尾
    mylist.splice(mylist.end(), otherlist);


std::forward_list 核心知识点总结

一、基础概念与特性
  1. 单向链表结构
    C++11 引入的‌单向链表‌容器,每个节点包含数据值和指向下一节点的指针
  2. 最小化内存开销
    相比 std::list 节省内存(每个节点少一个指针)
  3. 迭代器特性
    仅支持‌前向迭代器‌(不可反向遍历)

二、内存管理机制
特性说明
默认分配器std::allocator<T>
节点结构{ data, next_ptr }(仅含数据域和单向指针)
内存分配插入操作时动态分配新节点(如 push_front, insert_after
内存释放删除操作立即释放节点内存(如 pop_front, erase_after
内存碎片高频插入删除可能产生碎片(但比 std::list 碎片少 25%)
节点结构示例‌:

三、核心操作特性
操作时间复杂度说明
头部插入O(1)push_front() 在链表头插入新元素
指定位置后插入O(1)insert_after(pos) 在迭代器 pos 后插入元素
头部删除O(1)pop_front() 删除首元素
指定位置后删除O(1)erase_after(pos) 删除 pos 后元素
元素查找O(n)必须从头节点开始顺序遍历
迭代器稳定性✅ 稳定插入/删除操作‌不影响其他迭代器‌(除被删元素的迭代器)

四、特殊成员函数
  1. 首前迭代器
    before_begin():返回首元素前的虚拟节点迭代器(用于首元素操作)
    auto it = flist.before_begin();
    flist.insert_after(it, 42); // 在链表头插入


std::array 核心知识点总结

一、基础概念与特性
  1. 固定大小数组容器
    C++11 引入的‌静态连续数组‌容器,封装原生数组
  2. 内存分配方式
    元素在‌栈内存‌或‌全局/静态存储区‌分配(与原生数组相同)
  3. 零额外开销
    相比原生数组,不增加任何空间或时间开销(编译期确定大小)

二、模板参数与声明
template<classT,// 元素类型 std::size_t N // 数组固定大小>classarray;

关联容器(基于键值存储,允许快速查找)
‌有序关联容器‌(元素按键排序):



std::set 核心知识点总结

一、基础概念与特性
  1. 有序关联容器
    存储‌唯一键值‌(无重复元素)并自动按键排序
  2. 红黑树实现
    基于‌红黑树‌(自平衡二叉搜索树)实现,保证操作效率
  3. 自动排序机制
    元素始终‌按键升序排列‌(默认std::less<Key>

二、内存管理机制
特性说明
默认分配器std::allocator<Key>
节点内存分配每个元素独立分配内存(含数据+父/子指针+颜色标志)
分配触发时机insert() 操作时动态分配新节点
内存释放时机erase() 操作时立即释放节点内存
内存布局树形结构存储,节点间‌非连续内存
节点结构示例‌:

三、核心操作特性
操作时间复杂度说明
插入元素O(log n)insert(key)emplace(args)
删除元素O(log n)erase(key)erase(iterator)
查找元素O(log n)find(key)/contains(key)(C++20)
范围查询O(log n)lower_bound()/upper_bound() 实现高效范围扫描
迭代器稳定性✅ 稳定插入/删除操作‌不影响其他迭代器‌(除被删元素的迭代器)

四、模板参数
template<classKey,// 元素类型(必须支持严格弱序比较)classCompare= std::less<Key>,// 比较器(默认升序)classAllocator= std::allocator<Key>// 内存分配器>classset;


std::multiset 核心知识点总结

一、基础概念与特性
  1. 有序关联容器
    存储‌可重复键值‌的集合,元素自动按键排序
    set是多了判断是否重复
  2. 红黑树实现
    基于‌红黑树‌(自平衡二叉搜索树)实现
  3. 自动排序机制
    元素始终‌按键升序排列‌(默认std::less<Key>

二、内存管理机制
特性说明
默认分配器std::allocator<Key>
节点结构每个节点包含:
- 键值数据
- 父/子节点指针
- 红黑树颜色标志
内存分配insert() 操作时动态分配新节点
内存释放erase() 操作时立即释放节点内存
内存布局树形结构存储,节点间‌非连续内存
内存占用每个节点额外开销约 3 指针 + 1 bool(通常 16-32 字节)
节点结构示例‌:

三、核心操作特性
操作时间复杂度说明
插入元素O(log n)insert(key) 可重复插入相同键值
删除元素O(log n)erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
元素计数O(log n)count(key) 返回匹配键值的元素数量
范围查询O(log n)equal_range(key) 获取相同键值元素的范围迭代器对
迭代器稳定性✅ 稳定插入/删除操作‌不影响其他迭代器

四、模板参数
template<classKey,// 元素类型(必须支持严格弱序比较)classCompare= std::less<Key>,// 比较器(默认升序)classAllocator= std::allocator<Key>// 内存分配器>classmultiset;


std::map 核心知识点总结

一、基础概念与特性

  1. 容器类型
    C++ STL 中的‌有序关联容器‌,存储键值对(key-value pairs
  2. 排序特性
    元素始终‌按键(key)自动排序‌(默认升序)
  3. 键唯一性
    每个键在 std::map 中‌唯一‌(不允许重复键)
  4. 底层实现
    基于‌红黑树‌(自平衡二叉搜索树)实现,保证操作效率

二、内存管理机制

特性说明
默认分配器std::allocator<std::pair<const Key, T>>
内存分配方式动态分配(堆内存),每个节点独立分配
分配触发时机插入新元素时为键值对分配内存;删除时释放对应内存
内存布局树形结构存储,每个节点包含:父/子指针、颜色标志、键值对数据
连续内存❌ 元素在内存中‌非连续存储‌,迭代器遍历可能产生缓存未命中
示例节点结构(简化):

三、核心操作特性

操作时间复杂度说明
插入O(log n)insert()emplace() 添加新元素
查找O(log n)find()/count()/contains()(C++20)
删除O(log n)erase() 移除指定键或迭代器位置元素
访问O(log n)operator[] 访问或创建元素;at() 边界检查访问
范围查询O(log n)lower_bound()/upper_bound() 实现高效范围扫描

四、模板参数与自定义

template<classKey,// 键类型(必须支持严格弱序比较)classT,// 值类型classCompare= std::less<Key>,// 比较器(默认升序)classAllocator= std::allocator<std::pair<const Key, T>>// 内存分配器>classmap;


std::multimap 核心知识点总结

一、基础概念与特性
  1. 有序关联容器
    存储‌可重复键值对‌(允许相同键对应多个值)
  2. 红黑树实现
    基于‌红黑树‌(自平衡二叉搜索树)实现
  3. 自动排序机制
    元素始终‌按键升序排列‌(默认std::less<Key>

二、内存管理机制
特性说明
默认分配器std::allocator<std::pair<const Key, T>>
节点结构每个节点包含:
- 键值对数据
- 父/子节点指针
- 红黑树颜色标志
内存分配insert() 操作时动态分配新节点
内存释放erase() 操作时立即释放节点内存
内存布局树形结构存储,节点间‌非连续内存
节点结构示例‌:

三、与 std::map 的关键区别
特性std::multimapstd::map
键唯一性❌ 允许重复键✅ 键必须唯一
插入行为总是成功(不覆盖)键存在时插入失败或覆盖值
operator[]❌ 不支持✅ 支持(自动创建键)
查找返回值返回匹配键的范围迭代器返回单个元素迭代器
典型应用场景一对多关系(如电话簿同名条目)键值唯一映射(如ID映射)

四、核心操作特性
操作时间复杂度说明
插入元素O(log n)insert({key, value}) 可重复插入相同键值对
删除元素O(log n)erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
键值查找O(log n)find(key) 返回首个匹配键值的迭代器
范围查询O(log n)equal_range(key) 获取相同键值的迭代器范围
元素计数O(log n)count(key) 返回匹配键值的元素数量

五、特殊成员函数
  1. 键值范围访问
    equal_range(key):获取相同键值的迭代器范围
    auto [first, last] = phonebook.equal_range(“Alice”);
    for (auto it = first; it != last; ++it)
    std::cout << it->second; // 输出所有Alice的电话


std::unordered_set 核心知识点总结

一、基础概念与特性
  1. 无序关联容器
    C++11 引入的‌哈希集合‌,存储‌唯一键值‌(无重复元素)
    相比unordered_map 仅存key 且不支持【】访问
  2. 哈希表实现
    基于‌哈希表‌(链地址法或开放寻址法)实现
  3. 无序存储
    元素存储顺序‌不固定‌,取决于哈希函数和桶分布

二、内存管理机制
特性说明
默认分配器std::allocator<Key>
桶数组结构维护‌动态数组‌存储桶指针(桶即链表头节点或开放寻址槽位)
节点内存分配插入时动态分配节点(含键值 + 链表指针)
扩容机制当负载因子(元素数/桶数)超过阈值(默认 1.0)时:
1. 桶数组翻倍扩容
2. 所有元素‌重新哈希‌到新桶
内存释放erase() 立即释放节点内存;桶数组在对象销毁时释放
典型节点结构‌(链地址法):

三、核心操作特性
操作平均复杂度最坏复杂度说明
插入元素O(1)O(n)insert(key)emplace(args)
删除元素O(1)O(n)erase(key)erase(iterator)
查找元素O(1)O(n)find(key)/contains(key)(C++20)
迭代器稳定性❌ 不稳定-扩容操作使‌所有迭代器失效

四、模板参数
template<classKey,// 键类型classHash= std::hash<Key>,// 哈希函数对象classKeyEqual= std::equal_to<Key>,// 键相等比较器classAllocator= std::allocator<Key>// 分配器>classunordered_set;


std::unordered_multiset 核心知识点总结

一、基础概念与特性
  1. 无序关联容器
    存储‌可重复键值‌的集合,元素顺序由哈希函数决定
  2. 哈希表实现
    基于‌链式哈希表‌实现(数组 + 链表冲突解决)
  3. 快速查找特性
    平均时间复杂度 O(1),最坏情况 O(n)

二、内存管理机制
特性说明
默认分配器std::allocator<Key>
桶数组结构动态数组存储桶指针(初始大小由实现定义)
节点内存分配每个元素独立分配节点(含键值 + 链表指针)
动态扩容当负载因子 (元素数/桶数) > max_load_factor()(默认1.0)时:
- 桶数组扩容(通常翻倍)
- 重新哈希所有元素
内存释放erase() 立即释放节点内存;桶数组在对象销毁时释放
节点结构‌:

三、核心操作特性
操作平均复杂度最坏复杂度说明
插入元素O(1)O(n)insert(key) 允许重复插入相同键值
删除元素O(1)O(n)erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
元素计数O(n)O(n)count(key) 返回匹配键值的元素数量
范围查询O(n)O(n)equal_range(key) 获取相同键值元素的范围迭代器对

四、模板参数
template<classKey,// 键类型classHash= std::hash<Key>,// 哈希函数对象classKeyEqual= std::equal_to<Key>,// 键相等比较器classAllocator= std::allocator<Key>// 分配器>classunordered_multiset;

std::unordered_map:哈希实现的键值对映射(键唯一)

哈希表核心知识点总结

一、基础结构
  1. 数组槽位
    • 哈希表的第一维是数组结构,称为"槽"(slots)或"桶"(buckets)
    • 每个槽存储键值对或冲突处理结构(链表/树的头节点)
二、容量机制
  1. 初始容量
    • 创建时指定(如 Java HashMap 默认 16,Go map 默认 8)
    • 未指定时采用语言/库默认值
  2. 动态扩容
    • 触发条件:元素数量 > 当前容量 × 负载因子(通常 0.5-0.75)
    • 扩容策略:
      • 倍增策略‌:容量翻倍(如 16 → 32),保持 2 的幂
      • 质数策略‌:取大于 2 倍容量的最小质数
    • 扩容后需‌重新哈希‌所有元素
三、内存分配机制
场景内存分配行为
首次初始化✅ 分配初始数组内存
触发扩容时✅ 分配新数组内存
链表法插入新键✅ 分配节点内存
开放寻址法插入新键❌ 使用预分配槽位
更新已存在键的值❌ 不分配新内存
四、冲突处理策略
  1. 链表法
    • 每个槽位维护链表结构存储冲突元素
    • 插入新键必分配节点内存
  2. 开放寻址法
    • 所有元素直接存储在数组槽位中
    • 通过线性探测/二次探测解决冲突
    • 插入新键通常不分配额外内存


std::unordered_multimap 核心知识点总结

一、基础概念与特性
  1. 无序关联容器
    C++11 引入的‌哈希键值对容器‌,允许‌重复键值‌(同键可对应多个值)
  2. 哈希表实现
    基于‌链式哈希表‌实现(数组 + 链表冲突解决)
  3. 无序存储特性
    元素顺序由‌哈希函数‌决定,遍历时无固定顺序

二、内存管理机制
特性说明
默认分配器std::allocator<std::pair<const Key, T>>
桶数组结构动态数组存储桶指针(初始大小由实现定义)
节点内存分配插入时动态分配节点(含键值对 + 链表指针)
动态扩容当负载因子 (元素数/桶数) > max_load_factor()(默认1.0)时:
1. 桶数组扩容(通常翻倍)
2. 所有元素‌重新哈希‌到新桶
内存释放erase() 立即释放节点内存;桶数组在对象销毁时释放
节点结构‌:

三、核心操作特性
操作平均复杂度最坏复杂度说明
插入元素O(1)O(n)insert({key, value}) 允许重复键值对插入
删除元素O(1)O(n)erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
键值查找O(1)O(n)find(key) 返回首个匹配键值的迭代器
范围查询O(1)O(n)equal_range(key) 获取相同键值的迭代器范围
迭代器稳定性❌ 不稳定-扩容操作使‌所有迭代器失效

四、模板参数
template<classKey,// 键类型classT,// 值类型classHash= std::hash<Key>,// 哈希函数对象classKeyEqual= std::equal_to<Key>,// 键相等比较器classAllocator= std::allocator<std::pair<const Key, T>>// 分配器>classunordered_multimap;

容器适配器(基于其他容器封装)

std::stack 核心知识点总结

一、基础概念与特性
  1. 容器适配器
    C++ STL 中的‌栈结构容器适配器‌,提供后进先出(LIFO)操作接口
  2. 底层容器依赖
    基于其他序列容器实现(默认使用 std::deque
  3. 受限访问
    仅允许在栈顶进行插入和删除操作

二、内存管理机制
特性说明
底层容器决定内存内存管理完全由底层容器(如 std::deque)负责
默认底层容器std::deque(分段连续存储,动态扩容)
内存分配行为遵循底层容器的分配策略:
- push() 可能触发扩容
- pop() 释放元素内存
无独立内存管理作为适配器不直接管理内存,完全依赖底层容器实现
当使用默认 std::deque 时:内存分段存储在固定大小块中动态扩容时分配新内存块不释放已分配的内存块直到对象销毁

三、核心操作接口
操作时间复杂度说明
入栈O(1)push(value) 在栈顶插入元素
出栈O(1)pop() 移除栈顶元素(不返回值)
访问栈顶O(1)top() 返回栈顶元素引用(空栈调用导致未定义行为)
容量查询O(1)size() 返回元素数量
empty() 判断是否为空

四、模板参数与自定义
template<classT,// 元素类型classContainer= std::deque<T>// 底层容器类型>classstack;


std::queue 核心知识点总结

一、基础概念与特性
  1. 容器适配器
    C++ STL 中的‌队列结构容器适配器‌,提供先进先出(FIFO)操作接口
  2. 底层容器依赖
    基于其他序列容器实现(默认使用 std::deque
  3. 受限访问
    仅允许在队尾插入元素,队头删除元素

二、内存管理机制
特性说明
底层容器决定内存内存管理完全由底层容器(如 std::deque)负责
默认底层容器std::deque(分段连续存储,动态扩容)
内存分配行为遵循底层容器的分配策略:
- push() 可能触发扩容
- pop() 释放元素内存
无独立内存管理作为适配器不直接管理内存,完全依赖底层容器实现
当使用默认 std::deque 时:内存分段存储在固定大小块中动态扩容时分配新内存块不释放已分配的内存块直到对象销毁

三、核心操作接口
操作时间复杂度说明
入队O(1)push(value) 在队尾插入元素
出队O(1)pop() 移除队头元素(不返回值)
访问队头O(1)front() 返回队头元素引用(空队列调用导致未定义行为)
访问队尾O(1)back() 返回队尾元素引用
容量查询O(1)size() 返回元素数量
empty() 判断是否为空

四、模板参数与自定义
template<classT,// 元素类型classContainer= std::deque<T>// 底层容器类型>classqueue;


std::priority_queue 核心知识点总结

一、基础概念与特性
  1. 容器适配器
    C++ STL 中的‌优先级队列‌容器适配器,提供基于优先级的元素访问
  2. 堆结构实现
    底层实现为‌二叉堆‌数据结构(默认最大堆)
  3. 访问特性
    • 仅能访问堆顶元素(优先级最高元素)
    • 不支持随机访问或迭代器遍历

二、内存管理机制
特性说明
底层容器决定内存内存管理由底层容器(默认 std::vector)负责
堆结构特性元素以‌完全二叉树‌形式存储,满足堆序性质
内存分配行为遵循底层容器的分配策略:
- push() 可能触发扩容
- pop() 释放元素内存
默认容器std::vector(连续内存存储,支持高效随机访问)
扩容机制当底层 vector 容量不足时:
1. 分配新内存
2. 迁移元素并重建堆
内存布局示例‌(最大堆):

三、核心操作接口
操作时间复杂度说明
插入元素O(log n)push(value) 插入元素并调整堆结构
删除堆顶O(log n)pop() 移除堆顶元素并调整堆结构
访问堆顶O(1)top() 返回堆顶元素引用(空队列调用导致未定义行为)
容量查询O(1)size() 返回元素数量
empty() 判断是否为空

四、模板参数与自定义
template<classT,// 元素类型classContainer= std::vector<T>,// 底层容器classCompare= std::less<typenameContainer::value_type>// 比较器>classpriority_queue;


std::bitset 核心知识点总结

一、基础概念与特性
  1. 固定大小位集合
    C++ STL 提供的‌固定长度位数组‌容器,用于高效处理二进制标志位
  2. 编译时确定大小
    大小 N 在编译时指定,无法运行时动态改变
  3. 内存高效存储
    每个位仅占 1 bit 空间,无额外内存开销

二、内存管理机制
特性说明
内存分配位置栈内存(或作为成员变量时随对象分配)
内存布局连续内存块存储,按机器字长(word)分组
内存计算总内存 = ceil(N / (sizeof(WordType) * CHAR_BIT)) * sizeof(WordType)
无动态内存不涉及堆内存分配,无析构释放操作
示例‌:
std::bitset<64> 在 64 位系统占用 8 字节(64/8=1 word)
std::bitset<65> 在 64 位系统占用 16 字节(65/64≈2 words)

三、核心操作接口
操作说明
位访问operator[] 访问特定位;test(pos) 带边界检查访问
位设置set(pos) 置位;reset(pos) 清零;flip(pos) 翻转
批量操作set() 全置位;reset() 全清零;flip() 全翻转
位运算支持 &, `
转换操作to_ulong()/to_ullong() 转整数;to_string() 转二进制字符串

四、特殊功能

位统计
count() 返回置位(1)的数量

std::bitset<8>bs(0b10101010); bs.count();// 返回 4

`std::valarray

概述

std::valarray 是 C++ 标准库中的一个类模板,用于表示和操作数值数组,支持元素级数学运算和各种下标访问方式。它旨在优化数值计算,避免别名问题,并允许编译器进行循环融合等优化。

关键点

  • 设计目的:专为高效数值数组操作设计,支持元素级运算、切片和间接访问,但不提供标准迭代器(如 vector)。
  • 优化特性:操作可能返回代理对象以减少临时对象,支持并行化和循环优化,但实际实现中优化程度有限。
  • 内存管理:元素连续存储在动态分配的数组中,默认构造函数不分配内存,其他构造函数根据大小分配;resize 可改变大小,可能导致重新分配。
  • 限制:模板参数 T 需为数值类型(如算术类型或 std::complex);不支持自定义分配器。
  • 争议与使用:虽标准但使用较少,常被 vector 或其他库取代;研究表明其性能优化在现代编译器中未充分实现,但适合简单数值任务。

基本用法

std::valarray 的实例化如 std::valarray<double> va(5);,创建大小为 5 的数组,所有元素默认初始化。支持如 va += 2.0; 的元素级运算,返回新 valarray 或修改原对象。

优势与注意事项

优势在于内置数学函数(如 sum、min)和运算符重载,便于数值代码编写。注意:resize 会使指针/引用失效;操作假设无别名以优化,但需小心使用。



std::valarray 详细说明

引言

std::valarray 是 C++ 标准库(头文件 <valarray>)中的类模板,用于表示数值数组并支持高效的元素级数学操作。它允许元素 wise 的算术运算、逻辑运算和各种下标操作,包括切片(slice)和间接访问(indirect)。 该类设计时考虑了无别名假设,类似于 C 语言的 restrict 关键字,从而允许编译器优化,如循环融合。 表达式如 v1 = a * v2 + v3; 可被优化为单次循环遍历。一些实现(如 GNU libstdc++ 和 LLVM libc++)内部使用表达式模板,但进一步优化较少见。 valarray 适合数值计算,但实际使用中常被 std::vector 或第三方库(如 Eigen)替代,因为其优化潜力在现代编译器中未完全实现。

valarray 的模板参数 T 必须满足 NumericType 要求,通常为算术类型、指针或类似 std::complex 的类。 它不支持标准容器接口(如迭代器),但 C++11 引入了 std::begin 和 std::end 的重载。

成员类型
  • value_type:T,即存储元素的类型。
构造函数

std::valarray 提供多种构造函数,用于创建空数组或初始化数组:

  • 默认构造函数valarray(),创建空数组(大小 0),不分配内存。
  • 大小指定valarray(size_t count),分配 count 个元素,每个元素值初始化(默认构造)。
  • 值初始化valarray(const T& val, size_t count),分配 count 个元素,每个拷贝自 val。
  • 数组拷贝valarray(const T* ptr, size_t count),从 ptr 指向的数组拷贝 count 个元素。
  • 初始化列表(C++11):valarray(initializer_list<T> ilist),从列表初始化,大小为列表长度。
  • 拷贝/移动构造函数valarray(const valarray&)valarray(valarray&&),分配与源相同大小的存储,并拷贝/移动元素。

析构函数 ~valarray() 释放内部存储。

成员函数

成员函数包括赋值、访问、运算和聚合操作:

  • 赋值operator=,赋值内容,可能导致重新分配。
  • 访问operator[],返回元素引用、切片(slice_array)或掩码子数组(mask_array)。
  • 一元运算符operator+operator-operator~operator!,对每个元素应用,返回新 valarray。
  • 复合赋值operator+= 等,对每个元素应用,返回 *this。
  • 交换swap,常数时间交换内容,不失效引用。
  • 大小size,返回元素数。
  • 调整大小resize(size_t new_size)resize(size_t new_size, const T& val),改变大小;若增大,新增元素默认/值初始化;若缩小,销毁多余元素;失效指针/引用。
  • 聚合summinmax,计算总和、最小/最大值。
  • 移位shift(零填充移位)、cshift(循环移位)。
  • 应用函数apply,对每个元素应用指定函数,返回新 valarray。
非成员函数
  • 交换(C++11):std::swap(std::valarray)
  • 迭代器(C++11):std::beginstd::end,返回指向开始/结束的指针。
  • 二元运算符operator+ 等,元素级应用,返回新 valarray。
  • 比较运算符operator== 等,元素级比较,返回 bool valarray。
  • 数学函数absexplogpowsqrtsincos 等,元素级应用,返回新 valarray。
运算符
  • 一元:成员函数形式,对元素应用。
  • 复合赋值:成员函数,修改自身。
  • 二元:非成员,元素级运算,支持 valarray 与 valarray 或 scalar。
  • 比较:非成员,返回 bool valarray。
内存分配与管理

std::valarray 的元素存储在连续的动态分配数组中,类似于 std::vector 但无完整迭代器支持。 默认构造函数不分配内存。 其他构造函数根据指定大小在堆上分配连续块,并初始化元素。 resize 操作可能导致重新分配:若新大小大于当前,分配更多空间并初始化新增元素;若小于,销毁多余元素并可能释放内存。 实现可能使用 copy-on-write 或 copy-on-reference 优化以减少拷贝。 无自定义分配器支持;resize 或赋值失效所有指针/引用。 一些实现(如 Microsoft)提供非标准 free() 以释放存储。

辅助类与高级特性
  • 切片与子数组:使用 std::slicestd::gsliceslice_arraygslice_arraymask_arrayindirect_array 支持子集操作。
  • 模板参数推导(C++17):支持从初始化列表等推导 T。
  • 并行化潜力:设计允许操作并行执行,但依赖实现。
示例
#include<valarray>#include<iostream>intmain(){ std::valarray<int> va ={1,2,3,4}; va +=5;// 元素级加法: {6,7,8,9} std::cout << va.sum()<< std::endl;// 输出 30 va.resize(2);// 变为 {6,7}return0;}

此示例展示基本运算和 resize。

表格:常见成员函数总结
函数描述返回类型注意事项
size返回元素数size_t常量时间
resize改变大小void可能失效引用
sum元素总和T假设 T 支持 +
min/max最小/最大T假设 T 支持 <
apply应用函数valarray返回新数组
shift/cshift移位valarrayshift 零填充,cshift 循环
swap交换void常数时间,不失效引用
表格:运算符支持
类型示例行为
一元+va, -va新 valarray,元素应用
二元va1 + va2新 valarray,元素级
复合va += scalar修改 va
比较va1 == va2bool valarray,元素级
数学std::sin(va)新 valarray,元素应用

Read more

2026年Python+AI学习路线完整指南:从零基础到实战专家

2026年Python+AI学习路线完整指南:从零基础到实战专家

✨道路是曲折的,前途是光明的! 📝 专注C/C++、Linux编程与人工智能领域,分享学习笔记! 🌟 感谢各位小伙伴的长期陪伴与支持,欢迎文末添加好友一起交流! 📊 目录 * 为什么选择Python+AI * AI技术领域分布 * 完整学习路径 * 分阶段学习指南 * 实战代码示例 * 学习资源推荐 * 常见问题解答 为什么选择Python+AI? Python已成为人工智能领域最主流的编程语言,根据Stack Overflow 2024年开发者调查,Python在AI/ML领域的使用率超过85%。 Python在AI领域的优势 优势说明🐍 语法简洁上手快,专注算法本身而非语法细节📦 生态丰富NumPy、Pandas、PyTorch等成熟库👥 社区活跃海量教程、开源项目和问题解答🔧 工具完善Jupyter、Colab等优秀开发环境🚀 部署便捷Flask/FastAPI快速构建AI服务 AI技术领域分布 了解AI各领域的占比,帮助你更好地规划学习重点: 35%30%15%12%5%3%2025年AI技术领域市场需求分布机器

By Ne0inhk
GESP C++一级认证完全指南:考点解析与备考策略

GESP C++一级认证完全指南:考点解析与备考策略

引言 GESP(Grade Examination of Software Programming)是由中国计算机学会(CCF)主办的青少年编程能力等级认证,近年来已成为衡量中小学生编程水平的重要标尺。对于初涉C++语言的考生而言,一级认证既是入门第一关,也是奠定后续等级基础的关键一步。本文基于官方考纲与历年真题趋势,系统梳理GESP一级认证的注意事项、核心考点及备考策略,旨在为考生提供一份清晰、实用的备考指南。 一、考前必读:认证流程与注意事项 1.1 认证时间与形式 GESP每年举办多次认证,以第13次认证为例,1-4级考试时间为上午9:30-11:30,共计120分钟。认证采用全国统一命题、线下机考的形式,考生须在规定时间内前往指定考点参加考试。 1.2 准考证与证件准备 考生需在考前5天左右登录GESP官网下载并打印纸质准考证。打印后务必核对三项关键信息:考点地址(精确到教学楼及机房号)、考试时间、报考语言与等级。考试当日须携带纸质准考证及身份证件原件(身份证/户口本/护照/港澳台通行证)提前30分钟抵达考点。

By Ne0inhk
【算法通关指南:数据结构和算法篇】算法里的 “排队系统”:队列的数组模拟 + STL queue 实战

【算法通关指南:数据结构和算法篇】算法里的 “排队系统”:队列的数组模拟 + STL queue 实战

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人方向学习者 ❄️个人专栏:《算法通关指南》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、队列的概念 * 二、队列的模拟实现 * 2.1创建 * 2.2 入队 * 2.3出队 * 2.4队头 * 2.5队尾 * 2.6判空 * 2.7有效元素个数 * 2.8 所有测试代码 * 三、queue * 3.1 如何创建 * 3.2容器相关接口 * 3.2.1 size / empty * 3.2.2 push

By Ne0inhk