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

第一篇:语言基础

第二篇:设计模式

第三篇:数据库

第四篇:计算机网络

第五篇:操作系统

第六篇:LInux

第七篇:数据结构

第八篇:智力题

【61】静态变量什么时候初始化?

对于C语言的全局和静态变量,初始化发生在任何代码执行之前,属于编译期初始化。,静态变量只初始化一次,通过赋值方式多次修改静态变量的值

而C++标准规定:全局或静态对象当且仅当对象首次用到时才进行构造。

链接

1.先构造自己的父类,若是有静态成员对象,最先构造静态成员对象的父类,然后是静态成员对象,在其次是自己父类构造2.其他非静态成员对象的构造3.自己的构造函数静态成员构造 父类构造 非静态成员构造 子类构造

局部变量是在函数调用时赋初值,用到才赋初值,可以多次赋初值

作用域:C++里作用域可分为6种:全局,局部,类,语句,命名空间和文件作用域。静态全局变量 :全局作用域+文件作用域,所以无法在其他文件中使用。静态局部变量 :局部作用域,只被初始化一次,直到程序结束(。如果未初始化,默认0)类静态成员变量:类作用域。

所在空间:都在静态存储区。因为静态变量都在静态存储区,所以下次调用函数的时候还是能取到原来的值。

生命周期:静态全局变量、静态局部变量都在静态存储区,直到程序结束才会回收内存。类静态成员变量在静态存储区,当超出类作用域时回收内存。

【62】静态局部变量,全局变量,局部变量的特点,以及使用场景

首先从作用域考虑:C++里作用域可分为6种:全局,局部,类,语句,命名空间和文件作用域。

全局变量:全局作用域,可以通过extern作用于其他非定义的源文件。静态全局变量 :全局作用域+文件作用域,所以无法在其他文件中使用。

局部变量:局部作用域,比如函数的参数,函数内的局部变量等等。静态局部变量 :局部作用域,只被初始化一次,直到程序结束。从所在空间考虑:除了局部变量在栈上外,其他都在静态存储区。因为静态变量都在静态存储区,所以下次调用函数的时候还是能取到原来的值。

生命周期: 局部变量在栈上,出了作用域就回收内存;而全局变量、静态全局变量、静态局部变量都在静态存储区,直到程序结束才会回收内存。

使用场景:从它们各自特点就可以看出各自的应用场景,不再赘述。

【63】全局变量和局部变量有什么区别?

生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁;局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;

使用方式不同:通过声明后全局变量在程序的各个部分都可以用到;局部变量分配在堆栈区,只能在局部使用。

操作系统和编译器通过内存分配的位置可以区分两者,全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面 ,运行时加载。

【64】怎样判断两个浮点数是否相等?

对两个浮点数判断大小和是否相等不能直接用==来判断,会出错!明明相等的两个数比较反而是不相等!对于两个浮点数比较只能通过相减并与预先设定的精度比较,记得要取绝对值!浮点数与0的比较也应该注意。与浮点数的表示方式有关

【65】指针加减计算要注意什么?

指针每移动一位,它实际跨越的内存间隔是指针类型的长度,建议都转成10进制计算,计算结果除以类型长度取得结果

【66】nullptr调用成员函数可以吗?为什么?

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针能。因为在编译时对象就绑定了函数地址,和指针空不空没关系。

【67】C++中的指针参数传递和引用参数传递有什么区别?底层原理你知道吗?

指针参数传递本质上是值传递,它所传递的是一个地址值。

引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,存放的是由主调函数放进来的实参变量的地址。

引用传递和指针传递是不同的,虽然他们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将应用不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量(地址),那就得使用指向指针的指针或者指针引用。,而引用传参可以

【68】类如何实现只能静态分配和只能动态分配

  1. 建立类的对象有两种方式: ① 静态建立,静态建立一个类对象,就是由编译器为对象在栈空间中分配内存;A() ② 动态建立,A *p = new A();动态建立一个类对象,就是使用new运算符为对象在堆空间中分配内存。这个过程分为两步,第一步执行operator new()函数,在堆中搜索一块内存并进行分配;第二步调用类构造函数构造对象; 前者是把new、delete运算符重载为private属性。 这样做的原因:private属性的成员无法被外部调用,因为无法通过new动态创建对象;

后者是把构造、析构函数设为private属性,这样做的原因:将析构和构造设置为protected属性后,此函数能够被继承,但是不能被外部调用,导致无法通过静态方式外部调用构造函数创建对象;可通过子类来创建;

【69】想将某个类用作基类,为什么该类必须定义而非声明?

派生类中包含并且可以使用它从基类继承而来的成员,为了使用这些成员,派生类必须知道他们是什么。所以必须定义而非声明

【70】inline内联函数和define宏函数的区别

宏函数不是函数,但是使用起来像函数。预处理器用复制宏代码的方式代替函数的调用,省去了函数压栈退栈过程,提高了效率;而内联函数本质上是一个函数,内联函数一般用于函数体的代码比较简单的函数,不能包含复杂的控制语句,while、switch,并且内联函数本身不能直接调用自身。

宏函数是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换 ;而内联函数则是在编译的时候进行代码插入,编译器会在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用、入栈出栈的开销,提高效率

宏定义是没有类型检查的,无论对还是错都是直接替换;而内联函数在编译的时候会进行类型的检查,内联函数满足函数的性质,比如有返回值、参数列表等

  1. #define是关键字,inline是函数;
  2. 宏定义在预处理阶段进行文本替换,inline函数在编译阶段进行替换;
  3. inline函数有类型检查,相比宏定义比较安全; 内敛展开: 1、使用时的一些注意事项: 使用宏定义一定要注意错误情况的出现,比如宏定义函数没有类型检查,可能传进来任意类型,从而带来错误,如举例。还有就是括号的使用,宏在定义时要小心处理宏参数,一般用括号括起来,否则容易出现二义性

inline函数一般用于比较小的,频繁调用的函数,这样可以减少函数调用带来的开销。只需要在函数返回类型前加上关键字inline,即可将函数指定为inline函数。

同其它函数不同的是,最好将inline函数定义在头文件,而不仅仅是声明(申明和定义都需要inline),因为编译器在处理inline函数时,需要在调用点内联展开该函数,所以仅需要函数声明是不够的。

2、内联函数使用的条件:内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率 的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。以下情况不宜使用内联:(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。内联不是什么时候都能展开的,一个好的编译器将会根据函数的定义体,自动地取消不符合要求的内联。内联函数比宏函数更强大

A=11,b=25

【71】类与内联函数

1)类内定义的函数都是内联函数,不管是否有inline修饰符2)函数声明在类内,但定义在类外的看是否有inline修饰符,如果有就是内联函数,否则不是

【72】内联函数和函数的区别,内联函数的作用内联函数比普通函数多了关键字inline

内联函数避免了函数调用的开销;普通函数有调用的开销普通函数在被调用的时候,需要寻址(函数入口地址);内联函数不需要寻址。

内联函数有一定的限制,内联函数体要求代码简单,不能包含复杂的结构控制语句;普通函数没有这个要求。内联函数的作用:内联函数在调用时,是将调用表达式用内联函数体来替换。避免函数调用的开销。

在使用内联函数时,应注意如下几点: 在内联函数内不允许用循环语句和开关语句。 如果内联函数有这些语句,则编译将该函数视同普通函数那样产生函数调用代码,递归函数是不能被用来做内联函数的。内联函数只适合于只有1~5行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。 内联函数的定义必须出现在内联函数第一次被调用之前。

【73】接⼝继承和实现继承

声明⼀个纯虚函数的⽬的是为了让派⽣类只继承函数接⼝。 只提供接⼝,派⽣类根据⾃身去实现。声明⾮纯虚函数的⽬的是让派⽣类继承函数的接⼝和缺省实现

子类继承父类时,父类的纯虚函数必须重写,否则子类也是一个虚类不可实例化。父类中虚函数(非纯虚函数,即父类对其有定义),则子类也可以不重写,相当于原样继承了父类的虚函数。也可以重写,就相当于覆盖了父类的虚函数实现。不论是否重写虚函数都不影响子类的实例化~

【74】printf函数的实现原理是什么吗?

在C/C++中,对函数参数的扫描是从后向前的。C/C++的函数参数是通过压入堆栈的方式来给函数传参数的。栈是从内存的高地址向低地址生长的,控制生长的就是堆栈指针了

最先压入的参数是在最上面,就是说在所有参数的最后面,最后压入的参数在最下面,结构上看起来是第一个,所以最后压入的参数总是能够被函数找到,因为它就在堆栈指针的上方。

printf的第一个被找到的参数就是那个字符指针,就是被双引号括起来的那一部分,函数通过判断字符串里控制参数的个数来判断参数个数及数据类型,通过这些就可算出数据需要的堆栈指针的偏移量了printf("%d,%d",a,b);

【75】cout和printf有什么区别?

Cout 是ostream 类的一个对象,声明在iostream 文件中,属于std名字空间Printf速度比cout快,所以编程题超时时候可以试试换换输入输出

【76】运算符i++和++i的区别

赋值顺序不同:++ i 是先加后赋值;i ++ 是先赋值后加;++i和i++都是分两步完成的。效率不同:后置++执行速度比前置的慢。i++ 不能作为左值,而++i 可以:两者都不是原子操作。(原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束)

【77】Noexcept

阻止异常的扩散与传播申明不会出现异常,如果有异常,立刻终止程序,不会让异常传播和扩散

【78】new和malloc的区别,各自底层实现原理

new是C++关键字,也是操作符,需要编译器支持。而malloc是库函数,需要头文件支持。new分配内存按照数据类型进行分配,malloc分配内存按照大小分配。释放new需要delete,释放malloc需要free。new在调用的时候先分配内存,在调用构造函数,释放的时候调用析构函数;而malloc没有构造函数和析构函数。new返回类型为对应类型的指针,返回指针不用强转。,而malloc返回类型为void *,返回的指针要强转。new可以被重载;malloc不行:new可以为自定义类型的开辟内内存,而malloc不可以new分配内存更直接和安全。new发生错误抛出bac_alloc异常,malloc返回nullnew操作符从⾃由存储区上为对象动态分配内存空间,⽽malloc函数从堆上动态分配内存。

【79】malloc底层实现

在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由brk、mmap、,munmap这些系统调用实现的;

当开辟的空间小于 128K 时,调用 brk()函数;当开辟的空间大于 128K 时,调用mmap()分配内存。malloc采用的是内存池的管理方式,以减少内存碎片。先申请大块内存作为堆区,然后将堆区分为多个内存块。当用户申请内存时,直接从堆区分配一块合适的空闲快。 采用隐式链表将所有空闲块,每一个空闲块记录了一个未分配的、连续的内存地址。

调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。

【80】new和delete是如何实现

(分配内存+构造函数)(析构函数+释放内存)

• new的实现过程是:首先调用名为operator new的标准库函数,分配足够大的原始为类型化的内存,以保存指定类型的一个对象;接下来运行该类型的一个构造函数,用指定初始化构造对象;最后返回对应对象类型的指针

• delete的实现过程:对指针指向的对象运行适当的析构函数;然后通过调用名为operator delete的标准库函数释放该对象所用内存。

new在内存分配上面有一些局限性,new的机制是将内存分配和对象构造组合在一起,同样的,delete也是将对象析构和内存释放组合在一起的。allocator将这两部分分开进行,allocator申请一部分内存,不进行初始化对象,只有当需要的时候才进行初始化操作• malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。

【后续】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++、操作系统、数据库、计算机组成、计算机网络、设计模式、操作系统、牛客网服务器项目、综合智力题等

全部评论
感谢分享,加油牛友!😁
点赞 回复 分享
发布于 2024-04-23 19:14 山东

相关推荐

不愿透露姓名的神秘牛友
昨天 14:13
点赞 评论 收藏
分享
07-11 22:27
中南大学 Java
程序员牛肉:学历的话没问题。但是没问题的也就只有学历了。 其实你的整体架构是正确的,博客接着干。但是项目有点过于简单了。从后端的角度上讲,你这也就是刚入门的水平,所以肯定约面试够呛。 如果你要应聘后端岗位,那你第一个项目竟然是仿写操作系统。这个你要面试官咋问你。你一定要记住一点,你简历上写的所有的东西,都是为了证明你有能力胜任当前的岗位,而不是为了证明你自己会什么。 如果你只是浅浅的做几个项目,描述也都是烂大街。技术点也都是各种混水类的配置类需求,那你就不要幻想自己能走多远。一定要保持思考,保持学习。
点赞 评论 收藏
分享
评论
2
10
分享

创作者周榜

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