【15】C++岗位求职面试八股文系列文章(语言基础)

第一篇:语言基础

第二篇:设计模式

第三篇:数据库

第四篇:计算机网络

第五篇:操作系统

第六篇:LInux

第七篇:数据结构

第八篇:智力题

[261]存储器

CPU Cache(⽤的是⼀种叫 SRAM(Static Random-Access Memory,静态随机存储 器)的芯⽚)

内存⽤的芯⽚是⼀种叫作 DRAM (Dynamic Random Access Memory,动态随机存取存储器) 的芯⽚。存储器层次关系:CPU 并不会直接和每⼀种存储器设备直接打交道,⽽是每⼀种存储器设备只和它相邻的存储 器设备打交道。

[262]⻚⾯置换算法 内存淘汰算法(用于缺页中断)

最佳⻚⾯置换算法(OPT,未来最长时间不访问)、先进先出置换算法(FIFO)、最近最久未使⽤的置换算法(LRU)、时钟⻚⾯置换算法、最不常⽤算法(统计每个页面访问次数),LFU最不频繁使用页置换算法,淘汰掉使用频率最低的数据。如果存在相同使用频率的数据,则再根据使用时间间隔,将最久未使用的数据淘汰。

段页:程序的地址空间划分成多个拥有独⽴地址空间的段,每个段上的地址空间划分成⼤⼩相同的 ⻚。 这样既拥有分段系统的共享和保护,⼜拥有分⻚系统的虚拟内存功能. 分⻚主要⽤于实现虚拟内存,从⽽获得更⼤的地址空间;分段主要是为了使程序和数据可以被 划分为逻辑上独⽴的地址空间并且有助于共享和保护。

[263]为什么需要虚拟内存

虚拟内存的思想:通过结合磁盘和内存各⾃的优势,利⽤中间层对资源进⾏更合理地调度,充分提⾼资源的利⽤率。并提供和谐以及统⼀的抽象

  1. 虚拟内存可以结合磁盘和物理内存的优势为进程提供看起来速度⾜够快并且容ᰁ⾜够⼤的 存储
  2. 虚拟内存可以为进程提供独⽴的内存空间并引⼊多层的⻚表结构将虚拟内存翻译成物理内 存,进程之间可以共享物理内存减少开销,也能简化程序的链接、装载以及内存分配过 程;
  3. 虚拟内存可以控制进程对物理内存的访问,隔离不同进程的访问权限,提⾼系统的安全 性。

[264]排序算法选择

十大排序算法

稳定的有:插入,归并,冒跑 以及三种不常见的

快速排序最优的情况就是每一次取到的元素都刚好平分整个数组

时间nlogn 最坏n2空间:递归算进去的话logn

堆排序空间复杂度O(1):堆排序是原地排序,所以空间复杂度为O(1)递归快排,空间复杂度是lgN,

[265]C++模板是什么,你知道底层怎么实现的?

• 编译器并不是把函数模板处理成能够处理任意类的函数;编译器从函数模板通过具体类型产生不同的函数;编译器会对函数模板进行两次编译:在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。

• 这是因为函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中包含函数模板的头文件,如果该头文件中只有声明,没有定义,那编译器无法实例化该模板,最终导致链接错误

[266]构造函数和析构函数可以调用虚函数吗,为什么

  1. 在C++中,提倡不在构造函数和析构函数中调用虚函数; 无意义
  2. 构造函数和析构函数调用虚函数时都不使用动态联编,如果在构造函数或析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本;
  3. 因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化,因此调用子类的虚函数时不安全的,故而C++不会进行动态联编;
  4. 析构函数是用来销毁一个对象的,在销毁一个对象时,先调用子类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经销毁,这个时候再调用子类的虚函数没有任何意义。

[267]构造函数 析构函数可否抛出异常

不可以,C++只会析构已经完成的对象,对象只有在其构造函数执行完毕才算是完全构造妥当。在构造函数中发生异常,控制权转出构造函数之外。

因此,在对象b的构造函数中发生异常,对象b的析构函数不会被调用。因此会造成内存泄漏。用auto_ptr对象来取代指针类成员,便对构造函数做了强化,免除了抛出异常时发生资源泄漏的危机,不再需要在析构函数中手动释放资源

[268]类什么时候会析构?

  1. 对象生命周期结束,被销毁时;
  2. delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类虚构函数是虚函数时;
  3. 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

[269]纯虚函数

将虚函数定义为纯虚函数(纯虚函数无需定义,= 0只能出现在类内部虚函数的声明语句处;当然,也可以为纯虚函数提供定义,函数体可以定义在类的外部也可以定义在内部。

[270]构造函数、拷贝构造函数和赋值操作符的区别

构造函数对象不存在,没用别的对象初始化,在创建一个新的对象时调用构造函数

拷贝构造函数对象不存在,但是使用别的已经存在的对象来进行初始化

赋值运算符对象存在,用别的对象给它赋值,这属于重载“=”号运算符的范畴,“=”号两侧的对象都是已存在的

[271]拷贝构造函数和赋值运算符重载的区别?

• 拷贝构造函数是函数,赋值运算符是运算符重载。• 拷贝构造函数会生成新的类对象,赋值运算符不能。• 拷贝构造函数是直接构造一个新的类对象,所以在初始化对象前不需要检查源对象和新建对象是否相同;赋值运算符需要上述操作并提供两套不同的复制策略,另外赋值运算符中如果原来的对象有内存分配则需要先把内存释放掉。类中有指针变量时要重写析构函数、拷贝构造函数和赋值运算符

[272]模板类和模板函数的区别是什么?

函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定。

即函数模板允许隐式调用和显式调用而类模板只能显示调用。在使用时类模板必须加<T>,而函数模板不必

模板类参数从右到左,模板函数从左到右或者从右到左

[273]多继承的优缺点,作为一个开发者怎么看待多继承

• C++允许为一个派生类指定多个基类,这样的继承结构被称做多重继承。• 多重继承的优点很明显,就是对象可以调用多个基类中的接口;• 如果派生类所继承的多个基类有相同的基类,而派生类对象需要调用这个祖先类的接口方法,就会容易出现二义性

[274]为什么拷贝构造函数必须传引用不能传值

拷贝构造函数的作用就是用来复制对象的,在使用这个对象的实例来初始化这个对象的一个新的实例。

值传递: 对于内置数据类型的传递时,直接赋值拷贝给形参(注意形参是函数内局部变量); 对于类类型的传递时,需要首先调用该类的拷贝构造函数来初始化形参(局部对象);

引用传递: 无论对内置类型还是类类型,传递引用或指针最终都是传递的地址值!而地址总是指针类型(属于简单类型), 显然参数传递时,按简单类型的赋值拷贝,而不会有拷贝构造函数的调用(对于类类型). 上述1) 2)回答了为什么拷贝构造函数使用值传递会产生无限递归调用,内存溢出。拷贝构造函数用来初始化一个非引用类类型对象,如果用传值的方式进行传参数,那么传递实参需要调用拷贝构造函数,而拷贝构造函数需要传递实参,所以会一直递归。,内存溢出。

[275]虚函数的代价是什么?

• 带有虚函数的类,每一个类会产生一个虚函数表,用来存储指向虚成员函数的指针,• 带有虚函数的类的每一个对象,都会有有一个指向虚表的指针,会增加对象的空间大小;• 不能再是内联的函数,因为内联函数在编译阶段进行替代,而虚函数表示等待,在运行阶段才能确定到低是采用哪种函数,虚函数不能是内联函数

[276]什么情况下会合成构造函数?(默认生成一个构造函数)

  1. 如果一个类没有任何构造函数,但他含有一个成员对象,该成员对象含有默认构造函数,那么编译器就为该类合成一个默认构造函数,因为不合成一个默认构造函数那么该成员对象的构造函数不能调用;
  2. 没有任何构造函数的类派生自一个带有默认构造函数的基类,那么需要为该派生类合成一个构造函数,只有这样基类的构造函数才能被调用;
  3. 带有虚函数的类,虚函数的引入需要进入虚表,指向虚表的指针,该指针是在构造函数中初始化的,所以没有构造函数的话该指针无法被初始化;
  4. 带有一个虚基类的类

还有一点需要注意的是:

  1. 并不是任何没有构造函数的类都会合成一个构造函数
  2. 编译器合成出来的构造函数并不会显示设定类内的每一个成员变量

[277]什么时候需要合成拷贝构造函数呢?

• 对一个对象做显示的初始化操作,X xx = x;• 当对象被当做参数交给某个函数时;• 当函数传回一个类对象时;• 如果一个类没有拷贝构造函数,但是含有一个类类型的成员变量,该类型含有拷贝构造函数,此时编译器会为该类合成一个拷贝构造函数;• 如果一个类没有拷贝构造函数,但是该类继承自含有拷贝构造函数的基类,此时编译器会为该类合成一个拷贝构造函数;• 如果一个类没有拷贝构造函数,但是该类声明或继承了虚函数,此时编译器会为该类合成一个拷贝构造函数;• 如果一个类没有拷贝构造函数,但是该类含有虚基类,此时编译器会为该类合成一个拷贝构造函数

[278]哪些函数不能是虚函数?(大前提是类的成员函数)

  1. 构造函数,构造函数初始化对象,派生类必须知道基类函数干了什么,才能进行构造;当有虚函数时,每一个类有一个虚表,每一个对象有一个虚表指针,虚表指针在构造函数中初始化;
  2. 内联函数,内联函数表示在编译阶段进行函数体的替换操作,而虚函数意味着在运行期间进行类型确定,所以内联函数不能是虚函数;
  3. 静态函数,静态函数不属于对象属于类,静态成员函数没有this指针,因此静态函数设置为虚函数没有任何意义。
  4. 友元函数,友元函数不属于类的成员函数,不能被继承。对于没有继承特性的函数没有虚函数的说法。
  5. 普通函数,普通函数不属于类的成员函数,不具有继承特性,因此普通函数没有虚函数。 虚函数,它的函数指针会被存在虚函数表中,由于纯虚函数并没有具体的函数体,因此它在虚函数表中的值就为0,而具有函数体的虚函数则是函数的具体地址

[续]C++岗位求职面试八股文第十六篇(设计模式)

更多关于算法题解、软件开发面经、机器学习算法面经、各企业面试问题记录,关注Fintech砖,持续更新中。https://www.nowcoder.com/users/873777317

企业面试记录专栏https://www.nowcoder.com/creation/manager/columnDetail/0YBWnm

机器学习面经专栏https://www.nowcoder.com/creation/manager/columnDetail/j8nNy0

软件开发面经专栏https://www.nowcoder.com/creation/manager/columnDetail/0aXKaM

更多校园招聘常见面试问题(开发、算法、编程题目)参见CSDN博客:http://t.csdn.cn/V4qbH

欢迎关注、收藏、点赞后进行问题咨询及秋招建议!

#晒一晒我的offer##我的实习求职记录##软件开发薪资爆料##实习,投递多份简历没人回复怎么办##互联网没坑了,还能去哪里?#
软件开发八股面经 文章被收录于专栏

包含C++、操作系统、数据库、计算机组成、计算机网络、设计模式、操作系统、牛客网服务器项目、综合智力题等

全部评论

相关推荐

点赞 评论 收藏
分享
11-04 10:30
已编辑
门头沟学院 研发工程师
开心小狗🐶:“直接说答案”
点赞 评论 收藏
分享
评论
4
26
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务