首页 > 其他分享 >面试问题整理

面试问题整理

时间:2022-09-07 20:56:11浏览次数:77  
标签:扩容 函数 静态 成员 问题 面试 整理 数据结构 底层

项目相关 项目中用到的C++技术栈

1.vector扩容机制(扩容用到的STL器件?没答出来)

  • 两倍扩容问题:
    • 为什么呈倍数扩容(时间复杂度更优)
      • 对于n次插入操作, 采用成倍方式扩容可以保证时间复杂度O(n), 而指定大小扩容的时间复杂度为O(n^2)
    • 为什么是1.5倍扩容(空间可重用)
      • k == 2时:
        • 第n次扩容的时候需要分配的内存是:an = a1*q^(n-1) = 4*2^(n-1)
        • 而前n-1项的内存和为:Sn = a1*(1-q^(n-1))/(1-q) = 4*(1-2^(n-1)) /(1-2) = 4*2^(n-1)-4
        • 差值 = an - Sn = 4 > 0
        • 所以第n次扩容需要的空间恰好比前n-1扩容要求的空间总和要大,那么即使在前n-1次分配空间都是连续排列的最好情况下,也无法实现之前的内存空间重用
      • k = 1.5时:
        • n次扩容的时候需要分配的内存是:an = a1*q^(n-1) = 4*1.5^(n-1)
        • 而前n-1项的内存和为:Sn = a1*(1-q^(n-1))/(1-q) = 4*(1-1.5^(n-1)) /(1-1.5) = 8*1.5^(n-1)-8
        • 差值 = an - Sn = 8 - 4*1.5^(n-1)
        • n增长到一定的数值后,差值就会变为小于0,那么如果前n-1次分配的空间都是连续的情况下, 就可以实现内存空间复用

      1) 新增元素:vector 通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素;

    2) 对vector 的任何操作,一旦引起空间重新配置,指向原vector 的所有迭代器就都失效了;

    3) 初始时刻vector 的capacity 为0,塞入第一个元素后capacity 增加为1;

    4) 不同的编译器实现的扩容方式不一样,VS2015 中以1.5 倍扩容,GCC 以2 倍扩容。对比可以发现采用采用成倍方式扩容,可以保证常数的时间复杂度,而增加指定大小的容量只能达到O(n)的时间复杂度,因此,使用成倍的方式扩容。 

2.讲讲static关键字

  • 主要可以分为五个类型: 全局静态变量, 局部静态变量, 静态函数, 静态成员变量, 静态成员函数
    1. 全局静态变量
    • 在全局变量前加上关键字static,全局变量就定义成一个全局静态变量.
    • 内存中的位置:静态存储区,在整个程序运行期间一直存在。
    • 初始化:未经初始化的全局静态变量会被自动初始化为0(对于自动对象,如果没有显示初始化,会调用零参数构造函数,如不存在则编译失败);
    • 作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。
      1. 局部静态变量
    • 在局部变量之前加上关键字static,局部变量就成为一个局部静态变量。
    • 内存中的位置:静态存储区
    • 初始化:未经初始化的全局静态变量会被自动初始化为0(对于自动对象,如果没有显示初始化,会调用零参数构造函数,如不存在则编译失败);
    • 作用域:作用域仍为局部作用域,
      • 当定义它的函数或者语句块结束的时候,作用域结束。
      • 但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变;
  1. 静态函数
    • 在函数返回类型前加static,函数就定义为静态函数。函数的定义和声明在默认情况下都是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
    • 函数的实现使用static修饰,那么这个函数只可在本cpp内使用,不会同其他cpp中的同名函数引起冲突;
    • warning:不要再头文件中声明static的全局函数,不要在cpp内声明非static的全局函数,如果你要在多个cpp中复用该函数,就把它的声明提到头文件里去,否则cpp内部声明需加上static修饰;
  2. 类的静态成员
    • 在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。
    • 因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用
  3. 类的静态函数
    • 静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。
    • 在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。*如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:::();*参数表>静态成员函数名>类名>
    • 不能被virtual修饰,静态成员函数没有this 指针,虚函数的实现是为每一个对象分配一个vptr 指针,而vptr 是通过this 指针调用的,所以不能为virtual;虚函数的调用关系,this->vptr->ctable->virtual function

3.C++ STL容器和区别 迭代器

  • vector 底层数据结构为数组,支持快速随机访问
  • list 底层数据结构为双向链表,支持快速增删
  • deque 底层数据结构为一个中央控制器和多个缓冲区,详细见STL 源码剖析P146,支持首尾(中间不能)快速增删,也支持随机访问, deque 是一个双端队列(double-ended queue),也是在堆中保存内容的.它的保存形式 如下:[堆1] --> [堆2] -->[堆3] --> ..., 每个堆保存好几个元素,然后堆和堆之间有指针指向,看起来像是list 和vector 的结合品.
  • stack 底层一般用list deque 实现,封闭头部即可,不用vector 的原因应该是容量大小有限制,扩容耗时
  • queue 底层一般用list deque 实现,封闭头部即可,不用vector 的原因应该是容量大小有限制,扩容耗时(stack queue 其实是适配器,而不叫容器,因为是对容器的再封装)
  • priority_queue 的底层数据结构一般为vector 为底层容器,堆heap 为处理规则来管理底层容器实现
  • set 底层数据结构为红黑树,有序,不重复
  • multiset 底层数据结构为红黑树,有序,可重复
  • map 底层数据结构为红黑树,有序,不重复
  • multimap 底层数据结构为红黑树,有序,可重复
  • hash_set 底层数据结构为hash 表,无序,不重复
  • hash_multiset 底层数据结构为hash 表,无序,可重复
  • hash_map 底层数据结构为hash 表,无序,不重复
  • hash_multimap 底层数据结构为hash 表,无序,可重复

4.智能指针,shared_ptr 怎么解决其线程安全问题(weak_ptr)

5.程序从源代码到可执行文件的过程

6.防止内存泄露的方法

使用智能指针

7.C和C++申请动态内存的方法和不同

 

8.C++内存空间

  • 栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等其操作方式类似于数据结构中的栈。
  • 堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统)回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
  • 全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
  • 文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。
  • 程序代码区—存放函数体的二进制代码

9.数组和链表的区别

10.C++多态的几种方式

理解的虚函数和多态

  • 多态的实现主要分为动态多态和静态多态, 静态多态就是重载, 在编译的时候就已经确定了, 动态多态是用虚函数机制实现的, 在运行期间动态绑定. 例如如果父类中定义了虚函数,而派生类重写了此函数,此时通过一个指向派生类对象的父类指针调用此函数式, 子类中重写的函数将被调用.
  • 虚函数的实现: 在存在虚函数的类中会存在一个指向虚函数表的指针, 虚函数表中存放了虚函数的地址,当子类继承父类时也会继承其虚函数表, 当子类重写父类的虚函数时, 会将其继承的虚函数表中的地址替换为重写的函数地址. 使用虚函数,会增加访问内存的开销, 降低效率.

11.基类析构函数可以声明为虚函数吗 

 

标签:扩容,函数,静态,成员,问题,面试,整理,数据结构,底层
From: https://www.cnblogs.com/lhclqslove/p/16518948.html

相关文章

  • Mybatist-plus在开发过程中遇到的问题和解决办法
    1,总是老忘记一些LambdaQueryWrapper常用的表达式   2,minmaxsum等聚合函数的查询方法QueryWrapper<ParagonPrintLog>queryWrapper=newQueryWrappe......
  • 整理情绪的力量
    三个方法● 抽离,如厕策略● 关注解决方法● 使用积极的语言负面情绪克服列表● 生气课题分离,谁的问题谁解决● 烦躁降低要求● 孤独学会与孤独相处● 怨恨● ......
  • Hive重要知识点及面试题
    知识点:Hive是数据仓库建模工具之一。传统的关系数据库具有结构化程度高、独立性强、冗余度低,主要是操作型数据库和分析型数据库。其中操作型数据库:主要用于业务支撑。一......
  • System.Data.Linq 无法引用的问题
    参考文章 https://www.bbsmax.com/A/1O5EM0G457/已经在工程中引用了system.data.linq,但是在代码中,输入 usingSystem.Data.Linq 就报告不存在这个命名空间.修改一......
  • 肖sir ___海康面试题
    1、一个框为必填项     不输入的时候 可以点击提交        是前端bug 还是后端bug   2、前端做了校验 ,怎么判断后端有没有做校验3、一个字段校验不能......
  • 解决Microsoft store界面显示无网络连接或者下载的应用无网络连接无法使用的问题
    发现——电脑可以上网,但Microsoftstore界面显示无网络连接或者下载的应用无网络连接无法使用。思考:正常上网没问题,但只要与微软账户有关的软件均无法使用。解决:禁用网络......
  • EasyCVR云端录像模块无法进行下载是什么原因?该如何解决该问题?
    EasyCVR平台支持海量视频汇聚管理,能兼容多类型的设备接入,可覆盖市面上大多数的视频源设备,包括各种IPC、NVR、视频服务器、单兵设备、编码器设备等。平台也可支持多协议接入......
  • 浅谈双指针技巧(一)---通过双指针判断链表成环问题
    双指针是算法中非常重要的一个解决问题的思路。双指针顾名思义,就是有两个指针。根据双指针的方向及速度,我们一般将双指针分为以下几种场景1、快慢双指针2、左右双指针所谓......
  • Markdown 图片路径问题
    1.插入图片路径:本地目录1:./images/${filename}.assets  本地目录2:D:\docsify\images/${filename}  ......
  • SpringBoot解决BigDecimal传到前端后精度丢失问题
    1、局部处理(1)在相应字段上加@JsonFormat@JsonFormat(shape=JsonFormat.Shape.STRING)(2)在相应字段上加@JsonSerialize@JsonSerialize(using=ToStringSerializer.class......