《STL源码剖析》相关面试题总结

一、STL简介

STL提供六大组件,彼此可以组合套用:

  1. 容器
    容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种class template。
  2. 算法
    各种常见算法,如sort,search,copy,erase等,我觉得其中比较值得学习的就是sort,next_permutation,partition,merge sort,从实现角度看,STL算法是一种function template。
  3. 迭代器
    扮演容器与算法之间的胶合剂,是所谓的“泛型指针”。共有五种类型,从实现角度看,迭代器是一种将operator*,operator->,operator++,operator--等指针相关操作予以重载的class template。所有STL容器都附带有自己专属的迭代器,只有容器设计者才知道如何设计迭代器。原生指针也是一种迭代器。是设计模式的一种,所以被问到了解的设计模式可以用来凑数。
  4. 仿函数
    行为类函数,可作为算法的某种策略,从实现角度看,仿函数是一种重载了operator()的class或class template。一般函数指针可视为狭义的仿函数。
  5. 配接器
    一种用来修饰容器或者仿函数或迭代器接口的东西。比如queue和stack,看着像容器,其实就是deque包了一层皮。
  6. 配置器
    负责空间配置与管理。从实现角度看,配置器是一个实现了动态空间配置、空间管理、空间释放额class template。

二、关于容器的一些问题

2.1 当vector的内存用完了,它是如何动态扩展内存的?它是怎么释放内存的?用clear可以释放掉内存吗?是不是线程安全的?

  1. vector内存用完了,会以当前size大小重新申请2*size的内存,然后把原来的元素复制过去,把新元素插上,然后释放原来的内存。
  2. 一般我们释放vector里的元素使用clear,其实它不能释放内存,要想释放内存要使用swap,这样:
    1. vector<type> v;
    2. //.... 这里添加许多元素给v
    3. //.... 这里删除v中的许多元素
    4. vector<type>(v).swap(v);
    5. //此时v的容量已经尽可能的符合其当前包含的元素数量
    6. //对于string则可能像下面这样
    7. string(s).swap(s);
  3. 引用《effective stl》的第十二条:当涉及 STL容器和线程安全性时,你可以指望一个 STL库允许多个线程同时读一个容器,以及多个线程对不同的容器做写入操作。你不能指望 STL库会把你从手工同步控制中解脱出来,而且你不能依赖于任何线程支持。必须自己去写多线程安全措施。

2.2 map是怎么实现的?查找的复杂度是多少?能不能边遍历边插入?

  1. 红黑树和散列

  2. O(logn)

  3. 不可以,map不像vector,它在对容器执行erase操作后不会返回后一个元素的迭代器,所以不能遍历地往后删除。

2.3 写多读少应该用什么容器?

私以为是链表,链表的插入操作时常数时间复杂度,访问操作是O(n),是最适合写多读少的容器。

2.4 vector每次insert或erase之后,以前保存的iterator会不会失效?

理论上会失效,理论上每次insert或者erase之后,所有的迭代器就重新计算的,所以都可以看作会失效,原则上是不能使用过期的内存
但是vector一般底层是用数组实现的,我们仔细考虑数组的特性,不难得出另一个结论,

  1. insert时,假设insert位置在p,分两种情况:
    a) 容器还有空余空间,不重新分配内存,那么p之前的迭代器都有效,p之后的迭代器都失效
    b) 容器重新分配了内存,那么p之后的迭代器都无效咯

  2. erase时,假设erase位置在p,则p之前的迭代器都有效并且p指向下一个元素位置(如果之前p在尾巴上,则p指向无效尾end),p之后的迭代器都无效

2.5 hash_map和map的区别在哪里?

hash_map底层是散列的所以理论上操作的平均复杂度是常数时间,map底层是红黑树,理论上平均复杂度是O(logn),下面是借鉴的网上的总结:
这里总结一下,选用map还是hash_map,关键是看关键字查询操作次数,以及你所需要保证的是查询总体时间还是单个查询的时间。如果是要很多次操作,要求其整体效率,那么使用hash_map,平均处理时间短。如果是少数次的操作,使用 hash_map可能造成不确定的O(N),那么使用平均处理时间相对较慢、单次处理时间恒定的map,考虑整体稳定性应该要高于整体效率,因为前提在操作次数较少。如果在一次流程中,使用hash_map的少数操作产生一个最坏情况O(N),那么hash_map的优势也因此丧尽了。

2.6 为何map和set不能像vector一样有个reserve函数来预分配数据?

map和set内部存储的已经不是元素本身了,而是包含元素的节点。也就是说map内部使用的Alloc并不是map声明的时候从参数中传入的Alloc。例如:
map<int, int,="" less, Alloc > intmap;
这时候在intmap中使用的allocator并不是Alloc, 而是通过了转换的Alloc,具体转换的方法时在内部通过
Alloc::rebind重新定义了新的节点分配器,详细的实现参看彻底学习STL中的Allocator。
其实你就记住一点,在map和set里面的分配器已经发生了变化,reserve方法你就不要奢望了。

2.7 当数据元素增多时(10000和20000个比较),map和set的插入和搜索速度变化如何?

算一下就知道了,首先你得知道map和set的底层都是红黑树,红黑树的搜索近似于二分查找,二分查找呢,平均时间复杂度是log2n,这里简写成logn,
狂按计算器:
log(10000) = 13.3
log(20000) = 14.3
看到了不,理论上平均就多了一次,所以你懂的,插起来。。。

2.8 auto_ptr可以做vector的元素呢?为什么?

不能。因为STL的标准容器规定它所容纳的元素必须是可以拷贝构造和可被转移赋值的。而auto_ptr不能,可以用shared_ptr智能指针代替。

三、关于迭代器的一些问题

3.1 traits技术原理及应用

这个问题还真不知咋讲,简单来说,在STL算法中用到迭代器时(肯定会用到),会用到迭代器所指之物的型别,假设算法中有必要声明一个变量,以迭代器所指之物为型别,但是C++只支持sizeof()、并未
支持typeof()。即使typeid(),也只能获得型别名称,不能拿来声明变量,所以这里就要用到作为”特性萃取机“的traits技术,当然,要让traits有效运作,每个迭代器设计的时候的遵守约定,自行以内嵌型别定义的方式定义出相应型别。
详情请看书或者移步Traits技术:类型的if-else-then(STL核心技术之一)

四、关于算法的一些问题

4.1 快排算法的枢轴位置是怎么选择的?

三点中值法,取整个序列的头、尾、中央三个位置的元素,以其中值作为枢轴。

4.2 简单说一下next_permutation和partition的实现?

  1. next_permutation(下一个排列)
    首先,从最尾端开始往前寻找两个相邻元素,另第一个元素为i,第二个元素为ii,且满足i<ii。找到这样一组相邻元素后,再从尾端开始往前检验,找出第一个大于i的元素j,将i,j元素对调,再将ii之后的所有元素颠倒排列。此即所求“下一个”排列组合。

  2. partition
    令头端迭代器first向尾部移动,尾部迭代器last向头部移动。当first所指的值大于或等于枢轴时就停下来,当last所指的值小于或等于枢轴时也停下来,然后检验两个迭代器是否交错。如果first仍然在last左边,就将连着元素互换,然后各自调整一个位置(向中央逼近),再继续进行相同的行为。如果发现两个迭代器叫错了,表示整个序列已经调整完毕。

五、关于内存配置的一些问题

5.1 stl对于小内存块请求与释放的处理

STL考虑到小型内存区块的碎片问题,设计了双层级配置器,第一级配置直接使用malloc()和free();第二级配置器则视情况采用不同的策略,当配置区大于128bytes时,直接调用第一级配置器;当配置区块小于128bytes时,便不借助第一级配置器,而使用一个memory pool来实现。究竟是使用第一级配置器还是第二级配置器,由一个宏定义来控制。SGI STL中默认使用第二级配置器。
二级配置器会将任何小额区块的内存需求量上调至8的倍数,(例如需求是30bytes,则自动调整为32bytes),并且在它内部会维护16个free-list, 各自管理大小分别为8, 16, 24,…,128bytes的小额区块,这样当有小额内存配置需求时,直接从对应的free list中拔出对应大小的内存(8的倍数);当客户端归还内存时,将根据归还内存块的大小,将需要归还的内存插入到对应free list的最顶端。
小结:
STL中的内存分配器实际上是基于空闲列表(free list)的分配策略,最主要的特点是通过组织16个空闲列表,对小对象的分配做了优化。
1)小对象的快速分配和释放。当一次性预先分配好一块固定大小的内存池后,对小于128字节的小块内存分配和释放的操作只是一些基本的指针操作,相比于直接调用malloc/free,开销小。
2)避免内存碎片的产生。零乱的内存碎片不仅会浪费内存空间,而且会给OS的内存管理造成压力。
3)尽可能最大化内存的利用率。当内存池尚有的空闲区域不足以分配所需的大小时,分配算法会将其链入到对应的空闲列表中,然后会尝试从空闲列表中寻找是否有合适大小的区域,
但是,这种内存分配器局限于STL容器中使用,并不适合一个通用的内存分配。因为它要求在释放一个内存块时,必须提供这个内存块的大小,以便确定回收到哪个free list中,而STL容器是知道它所需分配的对象大小的,比如上述:
stl::vector array;
array是知道它需要分配的对象大小为sizeof(int)。一个通用的内存分配器是不需要知道待释放内存的大小的,类似于free(p)。
详情请看书或移步STL源码剖析---空间配置器

六、关于线程安全的一些问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464257.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VB.NET 中的ref 和C#中的ref 格式区别

今天把一个VB.NET的程序翻成C#的&#xff0c;在ref这堵了半天。函数定义是这样的&#xff1a;PublicSharedFunctionGetUsers(ByValportalId AsInteger, ByValisHydrated AsBoolean, ByValpageIndex AsInteger, ByValpageSize AsInteger, ByReftotalRecords AsInteger) AsArrayL…

工厂好的html页面,jquery中被誉为工厂函数的是什么?

jquery中被誉为工厂函数的是“$()”。在jQuery中&#xff0c;无论我们使用哪种类型的选择符都需要从一个“$”符号和一对“()”开始。下面本篇文章给大家介绍一下。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。jQuery的三种$()“$”…

如何学好单片机?​嵌入式第一门课

很多想学单片机的人问我的第一句话就是&#xff1a;怎样才能学好单片机&#xff1f;对于这个问题我今天就我自己是如何开始学单片机&#xff0c;如何开始上手&#xff0c;如何开始熟练这个过程给大家讲讲。先说说单片机&#xff0c;一般我们现在用的比较多的的MCS-51的单片机&a…

在 Mac 上通过 Docker 运行 Asp.net Core 简易教程

首先&#xff0c;你需要在 Mac 上安装好 Docker 下载地址 https://download.docker.com/mac/stable/Docker.dmg 或者查看别人的 安装教程 怎么安装这里就不在赘述了。 打开 Docker 输入命令 docker run -d --rm -p 8000:80 --name aspnetcore_sample microsoft/dotnet-sample…

TCP协议-相关面试题

一、TCP协议简介 一般问到TCP协议的时候 最常见的是TCP连接建立和断开的过程&#xff0c;也就是三次握手和四次挥手&#xff0c;两张图足矣。 1.1 三次握手 1.2 四次挥手 二、常见面试题 2.1 TCP连接阶段 2.1.1 发送序号和确认序号问题 例&#xff1a; TCP建立连接的过程采用三…

Android RIL源码研究笔记 の ril (一)

Android源码目录hardware/ril/libril中总共包含5个C/CPP文件&#xff0c;它们分别是ril_commands.h、ril_unsol_commands.h、ril_event.h、ril_event.cpp和ril.cpp。这篇文章主要分析ril.cpp文件。 我们可以将该文件划分为定义部分和实现部分&#xff0c;先来看定义部分&#x…

[转载]Manually configuring Microsoft Internet Information Services (IIS)

Manually configuring Microsoft Internet Information Services (IIS) 原文摘自http://publib.boulder.ibm.com/infocenter/wasinfo/v5r1//index.jsp?topic/com.ibm.websphere.base.doc/info/aes/ae/tins_manualWebIIS.html This topic describes manual configuration setti…

生活中的计算机趣味知识大全,五个有趣的电脑小知识

五个有趣的电脑小知识1&#xff0c; 更改临时文件夹的路径问&#xff1a;我使用的系统为Windows XP&#xff0c;我想把系统临时文件(Temp文件)存放区由C盘移到其他分区(如D盘)&#xff0c;请问该如何*作&#xff1f;答&#xff1a;在“我的电脑上点鼠标右键&#xff0c;选择“属…

稚晖君又整活啦!基于全志F1C200s的超迷你

转自全志在线B站最强小电视&#xff08;基于全志H3&#xff09;钢铁侠机械臂曾经靠着“B站最强小电视”以及号称“钢铁侠机械臂”等硬核产品出圈的稚晖君又双叒叕来整活啦&#xff01;稚晖君B站首页这次稚晖君开源了基于全志F1C200s的一个超迷你&低成本的Linux开发板&#…

分布式为什么使用Redis

一 为什么使用 Redis 在项目中使用 Redis&#xff0c;主要考虑两个角度&#xff1a;性能和并发。如果只是为了分布式锁这些其他功能&#xff0c;还有其他中间件 Zookpeer 等代替&#xff0c;并非一定要使用 Redis。 性能&#xff1a; 如下图所示&#xff0c;我们在碰到需要执行…

手动添加mysql服务

重新安装系统以后不再重新安装mysql 只需要我们把mysql服务添加到系统服务里即可,一下是具体步骤: 安装mysql服务 新建并编辑内容如下的一个bat文件&#xff0c;并且执行&#xff08;盘符:\mysql\bin\mysqld-nt.exe为安装目录&#xff0c;按实际情况填写,如果安装路径里面有空格…

心情

今天有些沮丧。 突然想起一句话&#xff1a; 千山暮雪&#xff0c;形影相吊&#xff01; 不知道是因为想起这句话才沮丧&#xff0c;还是因为心情差才想起这句话。 转载于:https://www.cnblogs.com/armlinux/archive/2006/12/20/2391047.html

微型计算机突然断电什么信息全部都是,微型计算机的硬件组成阶段作业(函授2014春).doc...

微型计算机的硬件组成阶段作业(函授2014春)微型计算机的硬件组成一、单项选择题(共15道小题&#xff0c;共15.0分)下列叙述中&#xff0c;错误的一个是个人微型计算机键盘上的Ctrl键是起控制作用的&#xff0c;它必须与其他键同时按下才有作用个人微型计算机在使用过程中突然断…

困扰多年的PCB散热问题终于可以解决了!

做电子的同学应该都会知道电路板&#xff0c;电路板分为基板导电部分组成。如下图&#xff0c;我们普通的单层电路板是一块有机材料加上导电铜层组成的。在大学那会我们会用面包板来做一些基础的实验&#xff0c;用面包板做实验可以减少打PCB板的时间&#xff0c;因为制作一个P…

进程之间的通信方式-共享内存

共享内存是被多个进程共享的一部分物理内存。共享内存是进程间共享数据的一种最快的方法&#xff0c;一个进程向共享内存区域写入了数据&#xff0c;共享这个内存区域的所有进程就可以立刻看到其中的内容。原理图如下&#xff1a; 共享内存的实现分为两个步骤&#xff1a; 一、…

第4天:调用样式表

用web标准设计网站&#xff0c;过渡的方法主要是采用XHTMLCSS&#xff0c;css样式表是必不可少的。这就要求所有网页设计师必须熟练掌握CSS&#xff0c;如果你以前不常用&#xff0c;那么现在就开始学习吧。要制作符合web标准的网站&#xff0c;不懂CSS是设计不出漂亮的页面的。…

获取url参数值(可解码中文值)

/*** 根据指定参数名称获取参数值* param {String} urlStr 参数名称* return {Object} 参数值* */ getUrlParams function (urlStr) {// 获取url中"?"符后的字串let url urlStr || location.href;let params {};if (url.indexOf(?) ! -1) {let str url.sub…

和一个刚毕业不久的朋友聊天

我记得还在你上大学的时候&#xff0c;我们就开始联系了&#xff0c;想不到的是你已经毕业半年多。我相信每个人都会有经历从学生到工作的过程&#xff0c;当然肯定也会因为工作后面对很多不一样的人和事&#xff0c;我也希望能够通过我们的一次对话&#xff0c;让没有毕业的同…

大工奥鹏计算机在线作业,大工20春《计算机网络技术》在线作业1题目【标准答案】...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼大工20春《计算机网络技术》在线作业1试卷总分:100 得分:100一、单选题 (共 10 道试题,共 50 分)1.网络协议是通信双方必须遵守的事先约定好的规则,一个网络协议由语法、语义和 ( ) 三部分组成。A.逆序B.次数C.时序D.词序2.运输层的…

xflash里的hello world程序

下面是hello world实例&#xff0c;虽然看起来与html里的按钮一样&#xff0c;但是&#xff0c;xflash里所有的元素都和页面无关&#xff0c;是纯flash的。从代码看&#xff0c;使用起来还是比较简单的&#xff0c;只需要包含xflash.js文件就可以满足进一步的开发要求了。 具体…