首页 > 编程语言 >C++面试八股文:std::vector和std::list,如何选择?

C++面试八股文:std::vector和std::list,如何选择?

时间:2023-06-24 19:02:13浏览次数:39  
标签:std node 面试官 list C++ vector 师兄

某日二师兄参加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
...
};

file

面试官:添加和删除元素会导致迭代器失效吗?

二师兄:并不会,因为在任意位置添加和删除元素只需要改变prev/next指针指向的对象,而不需要移动元素的位置,所以不会导致迭代器失效。

面试官:listvector相比,有哪些优势?什么情况下使用list,什么情况下使用vector

二师兄:主要有2点优势:1.list在随机插入数据不会导致数据的搬移。2.list随机删除也不会导致数据搬移。所以在频繁的随机插入/删除的场景使用list,其他场景使用vector

面试官:你知道std::sort和list成员函数sort有什么区别吗?

二师兄:std::sort是STL算法的一部分。它排序的容器需要有随机访问迭代器,所以只能支持vectordequelist成员函数sort用于list排序,时间复杂度是O(N*logN)

面试官:forward_list了解吗?知道如何实现的吗?

二师兄:std::forward_list是C++11引入的新容器之一。它的底层是单向链表,引入它的主要目的是为了达到手写链表的性能。同时节省了部分内存空间。(只有一根指针)

file

面试官:listpop_front/pop_back的时候需要注意哪些问题?

二师兄:需要判断listsize()不能为0,如果list为空,pop_front/pop_back会导致coredump

面试官:你知道list的成员函数insertforward_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

面试官:遍历两个元素数目相同的vectorlist,哪个效率高?

二师兄:vectorlist的遍历效率都是O(N),效率应该是一样的。

面试官:好的,回去等通知吧。

让我们看以下二师兄今日的表现:

以下代码的输出是什么?

这里实际上会输出Segmentation fault,原因是因为当从listerase这个node,这个nodeprevnext指针被清空,而++it是通过当前的nodenext指针去找下一个node,解引用一个空指针,导致coredump

erase函数返回下一个有效迭代器,所以可以把if(0 == *it % 2) li.erase(it)修改为if(0 == *it % 2) it = li.erase(it)来解决这个问题。

遍历两个元素数目相同的vectorlist,哪个效率高?

这里二师兄回答的倒是没有毛病,但是没有考虑到缓存问题。实际上因为vector底层采用数组存储数据,所以它的空间局部性更好,对缓存更友好(Cache-friendly),所以遍历vector的效率要高于遍历list

最后多啰嗦一点,如果你没有特别的理由选择其他容器,使用vector是最好的选择。

二师兄今日的面试旅程结束了,感谢各位小伙伴的关注和点赞。为了保证面试质量,以后不一定能保证日更。文章中有任何技术性问题,请留言反馈,在此感谢!

关注我,带你21天“精通”C++!(狗头)

标签:std,node,面试官,list,C++,vector,师兄
From: https://www.cnblogs.com/binarch/p/17501496.html

相关文章

  • Redis-list类型常用命令
    Redis-list常用命令lpush从左侧添加127.0.0.1:6379>lpushk1123455127.0.0.1:6379>lrangek10-154321  rpush从右侧添加127.0.0.1:6379>rpushk10-17127.0.0.1:6379>LRANGEk10-1543210-1  lrange遍历list127.0.0.1:6379>L......
  • [QML]从零开始QML开发(二)QML开发,浅谈控件、槽函数、锚等基本概念。QML和C++怎么交互?贯
    [QML]从零开始QML开发(二)QML开发,浅谈控件、槽函数、锚等基本概念。QML和C++怎么交互?贯彻落实MVC原则先看代码:importQtQuick2.12importQtQuick.Window2.12importQtQuick.Controls2.5Window{visible:truewidth:320height:480title:qsTr("HelloW......
  • C++ 核心指南之资源管理(上)
    C++核心指南(C++CoreGuidelines)是由BjarneStroustrup、HerbSutter等顶尖C++专家创建的一份C++指南、规则及最佳实践。旨在帮助大家正确、高效地使用“现代C++”。这份指南侧重于接口、资源管理、内存管理、并发等High-level主题。遵循这些规则可以最大程度地保证静......
  • Book-Effective C++ 改善程序与设计的55个具体做法
    Book-EffectiveC++改善程序与设计的55个具体做法让自己习惯C++AccustomingYourselftoC++条款01:视C++为一个语言联邦/ViewC++asafederationoflanguages.条款02:尽量以const,enum,inline替换#define/Preferconsts,enums,andinlinesto#defines.条款0......
  • [C/C++] Visual Stdio Code中多线程多源码文件编译、运行和调试
    搞了很久,记录一下:一.环境OS:Ubuntu20.04VSCode:1.77.0g++:g++(Ubuntu9.4.0-1ubuntu1~20.04.1)9.4.0二.配置文件下面两个文件先不要手动创建,下面第三章会讲到:task.json:编译程序的配置文件;launch.json:运行程序的配置文件.三.编译&运行1.打开main函数所在的cpp文......
  • C++面试八股文:聊一聊指针?
    C++面试八股文:聊一聊指针?某日二师兄参加XXX科技公司的C++工程师开发岗位第17面:面试官:聊一聊指针?二师兄:好的。面试官:你觉得指针本质上是什么?二师兄:这要从内存地址开始说起了。如果有一块容量是1G的内存,假设它的地址是从0x00000000到0x3fffffff,每一个字节都对应一个地......
  • C++面试八股文:std::vector了解吗?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第23面:面试官:vector了解吗?二师兄:嗯,用过。面试官:那你知道vector底层是如何实现的吗?二师兄:vector底层使用动态数组来存储元素对象,同时使用size和capacity记录当前元素的数量和当前动态数组的容量。如果持续的push_back(emplace_ba......
  • 《C++》员工管理系统
    学习差不多了,来小项目已经做两个晚上了目前只实现了批量添加和显示,数据结构采用链表......
  • C++ 类的基础知识
    1.类的定义类就是数据类型,是用户定义的数据类型,对象可以看成某个类的实例(某个类的变量)。所以说类是对象的封装,对象是类的实例。在类中定义的成员函数,都是inline函数。2.类的修饰符public、protected、private.public进行修饰的成员表示的是该类可以提供的接口、功能、或......
  • Window下的socket编程(c++实现)
    参考https://www.cnblogs.com/L-hq815/archive/2012/07/09/2583043.html 效果图: Sever.cpp点击查看代码#include<winsock2.h>#include<iostream>#include<string>usingnamespacestd;#pragmacomment(lib,"ws2_32.lib")intmain(intargc,......