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

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

时间:2023-07-01 22:55:57浏览次数:51  
标签:std node 面试官 list C++ vector 师兄

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指针指向的对象,而不需要移动元素的位置,所以不会导致迭代器失效。

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

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

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

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

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

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

面试官: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是最好的选择。

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

相关文章

  • 利用ccache提高c++编译速度
    首先安装ccache:sudoaptinstallccache然后在cmake文件中添加如下代码即可:find_program(CCACHE_FOUNDccache)if(CCACHE_FOUND)set_property(GLOBALPROPERTYRULE_LAUNCH_COMPILEccache)set_property(GLOBALPROPERTYRULE_LAUNCH_LINKccache)endi......
  • Redis数据结构——快速列表(quicklist)1
    Redis数据结构——快速列表(quicklist)一、什么是quicklistquicklist是Redis3.2版本以后针对链表和压缩列表进行改造的一种数据结构,是zipList和linkedList的混合体,相对于链表它压缩了内存。进一步的提高了效率。quicklist其实就是简单的双链表,但每个双链表节点中保存......
  • Redis数据结构——快速列表(quicklist)
    Redis数据结构——快速列表(quicklist)一、什么是quicklistquicklist是Redis3.2版本以后针对链表和压缩列表进行改造的一种数据结构,是zipList和linkedList的混合体,相对于链表它压缩了内存。进一步的提高了效率。quicklist其实就是简单的双链表,但每个双链表节点中保存......
  • 分布式文件存储 - FastDFS 工具类
    一、FastDFSClientpackagecom.changgou.file.util;importorg.csource.common.NameValuePair;importorg.csource.fastdfs.*;importorg.slf4j.LoggerFactory;importorg.springframework.core.io.ClassPathResource;importjava.io.ByteArrayInputStream;importjav......
  • C/C++《数据结构课程设计》题目[2023-07-01]
    C/C++《数据结构课程设计》题目[2023-07-01]《数据结构课程设计》题目一、【大数四则运算】——线性表[习题描述]设计—个实现任意长的整数进行四则运算和幂次运算的演示程序。[基本要求]利用双向循环链表实现大数的存储,每个结点含一个整型变量。[实现提示]实现原理:任何一......
  • C++ 编程中的核心知识点
    const作用修饰变量,说明该变量不可以被改变;修饰指针,分为指向常量的指针(pointertoconst)和自身是常量的指针(常量指针,constpointer);修饰引用,指向常量的引用(referencetoconst),用于形参类型,即避免了拷贝,又避免了函数对值的修改;修饰成员函数,说明该成员函数内不能修改成员......
  • C++之future
    背景在C++多线程编程中,同步线程间的操作和结果通常是一个关键问题。C++11引入了std::future这一同步原语,用于表示异步操作的结果。本文将介绍C++中std::future的使用方法、优势以及与其他同步方法的对比。使用std::futurestd::future表示一个异步操作的结果,可以用于获取操作的......
  • Qt/C++编写超精美自定义控件(历时9年更新迭代/超202个控件/祖传原创)
    一、前言无论是哪一门开发框架,如果涉及到UI这块,肯定需要用到自定义控件,越复杂功能越多的项目,自定义控件的数量就越多,最开始的时候可能每个自定义控件都针对特定的应用场景,甚至里面带了特定的场景的一些设置和处理,随着项目数量的增多,有些控件又专门提取出来共性,做成了通用的自定义......
  • 【零基础学习C++】如何写一个C++类?
    个人主页:【......
  • 《Linux C/C++ 服务器开发实践》记录
    《LinuxC/C++服务器开发实践》记录序言:该记录是一份读书笔记,因为主题需要和计算机操作系统有关,自然而然的想到Linux的学习,刚好最近找实习发现很多C++服务器方向需要熟悉Windows/Linux的多线程开发,所以就选了这本《LinuxC/C++服务器开发实践》来看,这本书有许多工作用得上的知......