C++面试八股文:std::vector和std::list,如何选择?
某日二师兄参加XXX科技公司的C++工程师开发岗位第24面:
面试官:
list
用过吗?二师兄:嗯,用过。
面试官:请讲一下
list
的实现原理。二师兄:
std::list
被称为双向链表,和C中手写双向链表本质上没有大的区别。list
对象中有两个指针,一个指向上一个节点(node
),一个指向下一个节点(node
)。二师兄:与手写双向链表不同的是,
list
中有一个base node
,此node
并不存储数据,从C++11开始,此node
中包含一个size_t
类型的成员变量,用来记录list
的长度。二师兄:所以说从C++11开始,
size()
的时间复杂度是O(1)
,在此之前是O(N)
。面试官:是每个
node
都包含一个记录长度的成员变量吗?二师兄:不是,GCC中的实现只有在
header node
上记录了长度信息,其他node
并没有记录。
struct _List_node_base
{
_List_node_base* _M_next;
_List_node_base* _M_prev;
...
};
struct _List_node_header : public _List_node_base
{
#if _GLIBCXX_USE_CXX11_ABI
std::size_t _M_size;
#endif
...
};
面试官:添加和删除元素会导致迭代器失效吗?
二师兄:并不会,因为在任意位置添加和删除元素只需要改变
prev/next
指针指向的对象,而不需要移动元素的位置,所以不会导致迭代器失效。面试官:
list
和vector
相比,有哪些优势?什么情况下使用list
,什么情况下使用vector
?二师兄:主要有2点优势:1.
list
在随机插入数据不会导致数据的搬移。2.list
随机删除也不会导致数据搬移。所以在频繁的随机插入/删除的场景使用list
,其他场景使用vector
。面试官:你知道
std::sort
和list成员函数sort
有什么区别吗?二师兄:
std::sort
是STL算法的一部分。它排序的容器需要有随机访问迭代器,所以只能支持vector
和deque
。list
成员函数sort
用于list
排序,时间复杂度是O(N*logN)
。面试官:
forward_list
了解吗?知道如何实现的吗?二师兄:
std::forward_list
是C++11引入的新容器之一。它的底层是单向链表,引入它的主要目的是为了达到手写链表的性能。同时节省了部分内存空间。(只有一根指针)
面试官:
list
在pop_front
/pop_back
的时候需要注意哪些问题?二师兄:需要判断
list
的size()
不能为0
,如果list
为空,pop_front/pop_back
会导致coredump
。面试官:你知道
list
的成员函数insert
和forward_list
的成员函数的insert_after
有什么区别?二师兄:两者都可以向特定位置添加元素。不同的是
insert
把元素插入到当前迭代器前,而insert_after
把元素插入到当前迭代器后。面试官:以下代码的输出是什么?
#include <iostream>
#include <list>
int main(int argc, char const *argv[])
{
std::list<int> li = {1,2,3,4,5,6};
for(auto it = li.begin(); it!= li.end(); ++it)
{
if(0 == *it % 2) li.erase(it);
}
for(auto& i : li) std::cout << i << " ";
std::cout << std::endl;
}
二师兄:应该是
1 3 5
。面试官:遍历两个元素数目相同的
vector
和list
,哪个效率高?二师兄:
vector
和list
的遍历效率都是O(N)
,效率应该是一样的。面试官:好的,回去等通知吧。
让我们看以下二师兄今日的表现:
以下代码的输出是什么?
这里实际上会输出Segmentation fault
,原因是因为当从list
中erase
这个node
,这个node
的prev
和next
指针被清空,而++it
是通过当前的node
的next
指针去找下一个node
,解引用一个空指针,导致coredump
。
erase
函数返回下一个有效迭代器,所以可以把if(0 == *it % 2) li.erase(it)
修改为if(0 == *it % 2) it = li.erase(it)
来解决这个问题。
遍历两个元素数目相同的
vector
和list
,哪个效率高?
这里二师兄回答的倒是没有毛病,但是没有考虑到缓存问题。实际上因为vector
底层采用数组存储数据,所以它的空间局部性更好,对缓存更友好(Cache-friendly
),所以遍历vector
的效率要高于遍历list
。
最后多啰嗦一点,如果你没有特别的理由选择其他容器,使用vector
是最好的选择。
二师兄今日的面试旅程结束了,感谢各位小伙伴的关注和点赞。为了保证面试质量,以后不一定能保证日更。文章中有任何技术性问题,请留言反馈,在此感谢!
关注我,带你21天“精通”C++!(狗头)
C++面试八股文:std::vector和std::list,如何选择?的更多相关文章
- 实战c++中的string系列--std:vector 和std:string相互转换(vector to stringstream)
string.vector 互转 string 转 vector vector vcBuf;string stBuf("Hello DaMao!!!");----- ...
- std::vector与std::list效能对比(基于c++11)
测试对象类型不同,数量级不同时,表现具有差异: 测试数据对象为std::function时: test: times(1000)vector push_back time 469 usvector e ...
- 编程杂谈——std::vector与List<T>的性能比较
昨天在比较完C++中std::vector的两个方法的性能差异并留下记录后--编程杂谈--使用emplace_back取代push_back,今日尝试在C#中测试对应功能的性能. C#中对应std:: ...
- Item 21: 比起直接使用new优先使用std::make_unique和std::make_shared
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 让我们先从std::make_unique和std::make_s ...
- 使用std::map和std::list存放数据,消耗内存比实际数据大得多
使用std::map和std::list存放数据,消耗内存比实际数据大得多 场景:项目中需要存储一个结构,如下程序段中TEST_DATA_STRU,结构占24B.但是使用代码中的std::list&l ...
- c++转载系列 std::vector模板库用法介绍
来源:http://blog.csdn.net/phoebin/article/details/3864590 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作 ...
- C++ 中的std::vector介绍(转)
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vec ...
- std::vector介绍
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vec ...
- std::vector<Channel2*> m_allChannels;容器,以及如何根据channelid的意义
std::vector<Channel2*> m_allChannels;容器,以及如何根据channelid的意义 这个容器保存了所有客户端连接的channel Channel2* Li ...
- std::vector数据复制
std::vector<boost::shared_ptr <ITEM> > srcItemList; // 数据源 std::vector<ITEM> des ...
随机推荐
- flask-sqlalchemy入门
Flask-SQLAlchemy 是一个为 Flask 应用增加 SQLAlchemy 支持的扩展.它致力于简化在 Flask 中 SQLAlchemy 的使用.SQLAlchemy 是目前pytho ...
- pandas之样本操作
随机抽样,是统计学中常用的一种方法,它可以帮助我们从大量的数据中快速地构建出一组数据分析模型.在 Pandas 中,如果想要对数据集进行随机抽样,需要使用 sample() 函数.sample() 函 ...
- [Java/LeetCode]算法练习:转变日期格式(1507/simple)
1 题目描述 题目来源: https://leetcode-cn.com/problems/reformat-date 给你一个字符串 date ,它的格式为 Day Month Year ,其中: ...
- 关于取消DevTools listening on ws://127.0.0.1…提示的方法
Python代码写好之后,通过任务计划程序定期执行.py文件,但总会有命令窗口,虽然不影响程序执行,但每次需要手动叉掉比较烦.于是我网上搜索了一些方法. 网上的方法并没有直接解决我的问题,但我借助搜索 ...
- JUC(二)线程间通信
目录 线程间通信 多线程编程步骤 一个加减实例 & 虚假唤醒问题 Lock接口实现 lock.newCondition设置等待条件 线程间定制化通信 线程间通信案例 设置标志位 线程间通信 多 ...
- 长连接Netty服务内存泄漏,看我如何一步步捉“虫”解决
作者:京东科技 王长春 背景 事情要回顾到双11.11备战前夕,在那个风雨交加的夜晚,一个急促的咚咚报警,惊破了电闪雷鸣的黑夜,将沉浸在梦香,熟睡的我惊醒. 一看手机咚咚报警,不好!有大事发生了!电话 ...
- [MAUI]模仿网易云音乐黑胶唱片的交互实现
@ 目录 创建页面布局 创建手势控件 创建影子控件 唱盘拨动交互 唱盘和唱针动画 项目地址 用过网易云音乐App的同学应该都比较熟悉它播放界面. 这是一个良好的交互设计,留声机的界面隐喻准确地向人们传 ...
- logstash增量同步mysql数据到es
本篇本章地址:https://www.cnblogs.com/Thehorse/p/11601013.html 今天我们来讲一下logstash同步mysql数据到es 我认为呢,logstash是众 ...
- [双目视差] 立体匹配算法推理 - SGBM算法(一)
文章目录 立体匹配算法推理 - SGBM算法(一) 一.SGBM与SGM的区别 二.代价计算 立体匹配算法推理 - SGBM算法(一) SGBM立体匹配算法,总体来讲包含以下6个步骤: Preproc ...
- 极速进化,光速转录,C++版本人工智能实时语音转文字(字幕/语音识别)Whisper.cpp实践
业界良心OpenAI开源的Whisper模型是开源语音转文字领域的执牛耳者,白璧微瑕之处在于无法通过苹果M芯片优化转录效率,Whisper.cpp 则是 Whisper 模型的 C/C++ 移植版本, ...