std::vector,std::deque,std…

本文详细对比了C++标准库中的三种容器:vector、deque和list。分别介绍了它们的内存分配方式、插入删除效率及随机访问特性,并给出了使用建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
vector    表示一段连续的内存区域,每个元素被顺序存储在这段内存中,对vector的随机访问效率很高,但对非末尾元素的插入和删除则效率非常低。

deque    也表示N段连续的内存区域组成,但与vector不同的是它支持高效地在其首部插入和删除元素,它通过两级数组结构来实现,一级表示实际的容器,第二级指向容器的首和尾  

list    表示非连续的内存区域并通过一对指向首尾元素的指针双向链接起来,插入删除效率高,随机访问效率低
      

使用:
它们的使用很相似,
#include <vector>
#include <deque>
#include <list>
下面是一段代码:
std::list<int> a;
a.push_back(5);//从尾部插入数据
a.push_front(7);//从头部插入数据
std::list<int>::iterator p=a.begin();//得到头部数据指针,把iterator 当成指针比较容易理解
*p=10;//修改头部数据
int i=*p;//得到数据
a.pop_front();//释放第一个数据

注意点
1.当执行大数据量的调用push_back()的时候,记住要调用vector::reserve()。
2.如果你计划使用insert(),或者需要pop_front(),那就使用deque。
3.deque是大块大块地分配内存,每次插入固定数量的数据。vector是就近分配内存(这可能不是一个坏的事情)。但我们应该关注是,vector每次增加的内存足够大的时候,在当前的内存不够的情况。deque不需要capacity()和reserve()> 是非常有道理的。
4.*.vector内部分配的内存是永不释放的,即使你调用clear()也不会,这一点很不好,有误导性.有可能一个vector只在瞬间需要很大的容量,但大多数时间只需要很小的容量,结果却是长时间的占用了很大的,没有被使用到的内存.vector也没有提供函数来释放它内部的内存,不过有一个简单的办法,前几天在网上找到的:
        i_math::vector<BYTE>buf;
        buf.resize(100000);//分配了一块至少100000 bytes的内存
        if (TRUE)//清空buf的内存
        {
                    i_math::vector<BYTE> t;
                    buf.swap(t);//把这块内存交换到一个临时的vector里去
        }
        assert(buf.capacity()==0);//内存被清空了
5.*.deque就不一样了,deque永远不会占用太多冗余的内存,你只需要把它resize()到一个你希望的大小,它会自动释放掉那些被多余占用的内存
6.vector还有一个不好的地方,当你往一个vector里添加一个成员的时候,所有指向这个vector的原来成员的指针就不能保证有效了,因为 vector会re-alloc内存.而deque不会,无论从前面还是后面添加新成员,旧的成员都不会移动位置,这一点有时候很有用.


### std::dequestd::vector 遍历性能对比 #### 性能概述 `std::vector` `std::deque` 是 C++ 标准库中两种常用的顺序容器,它们都支持随机访问迭代器。然而,在遍历性能方面存在一些细微差别。 对于 `std::vector` 而言,它的底层实现是一个连续的数组结构[^1]。这意味着所有的元素都被存储在一个连续的内存块中,这使得缓存友好度非常高。当进行线性遍历时,由于 CPU 缓存机制的作用,`std::vector` 的遍历通常具有较高的效率。 相比之下,`std::deque` 并不是一个单一的连续内存块,而是由多个固定大小的分段组成[^2]。虽然这种设计使其能够在两端高效地插入删除元素,但在遍历时可能会因为跨段而引入额外的开销。具体来说,每次跨越不同的分段时可能需要重新加载新的内存页到缓存中,从而降低缓存命中率并影响整体性能[^3]。 尽管如此,在某些特定条件下,比如大规模数据集上的复杂操作组合(如交替执行增删动作后再立即全量扫描),实验表明即使是在简单遍历环节,`std::deque` 仍有可能展现出优于 `std::vector` 的表现趋势[^4]。 以下是两个容器在不同情况下的理论优势总结: - **std::vector**: 更适合那些主要涉及大量读取或者仅偶尔修改内容的应用场合;得益于其紧凑布局带来的良好局部性高速缓存利用率。 - **std::deque**: 当程序逻辑频繁涉及到头部/尾部变动而又不可避免随后需完成整个集合的一次性审查,则该选项或许更佳。 #### 实际测试代码示例 下面提供了一段简单的测试代码来演示两者的区别: ```cpp #include <iostream> #include <vector> #include <deque> #include <chrono> const int N = 1e7; double measure_time(auto& container){ auto start = std::chrono::high_resolution_clock::now(); long sum=0; for(int i : container) { sum +=i ; } auto end = std::chrono::high_resolution_clock::now(); return std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()/1.e6; } int main(){ std::vector<int> vec(N); std::generate(vec.begin(),vec.end(),[](){return rand();}); std::deque<int> deq(N); std::generate(deq.begin(),deq.end(),[](){return rand();}); double t_vec =measure_time(vec); double t_deque=measure_time(deq); std::cout<<"Vector traversal time:"<<t_vec<<'\n'; std::cout<<"Deque traversal time: "<<t_deque<<'\n'; } ``` 此脚本创建了一个含有千万级整数的大规模向量以及双端队列实例,并分别测量了各自完整的单程迭代所需时间长度。实际运行结果将取决于具体的硬件环境配置等因素。 ### 结论 总体而言,如果仅仅是单纯考虑遍历速度的话,一般情况下应该优先选用 `std::vector` ,因为它具备更好的空间连贯性进而促进更快的数据获取过程。不过也要注意到特殊情形的存在——即当面临极其复杂的混合型任务负载模式之时,也许会出现例外状况致使采用 `std::deque` 成为了更为明智的选择方案之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值