【2】C++岗位求职面试八股文系列文章(语言基础)
第一篇:语言基础
第二篇:设计模式
第三篇:数据库
第四篇:计算机网络
第五篇:操作系统
第六篇:LInux
第七篇:数据结构
第八篇:智力题
[21]C++函数调用过程
函数的调用过程:1)从栈空间分配存储空间2)从实参的存储空间复制值到形参栈空间3)进行运算形参在函数未调用之前都是没有分配存储空间的,在函数调用结束之后,形参弹出栈空间,清除形参空间。数组作为参数的函数调用方式是地址传递,形参和实参都指向相同的内存空间,调用完成后,形参指针被销毁,但是所指向的内存空间依然存在,不能也不会被销毁。当函数有多个返回值的时候,不能用普通的 return 的方式实现,需要通过传回地址的形式进行,即地址/指针传递。
[22]C++函数调用的压栈过程
函数运行状态,函数参数(从右到左)、函数的返回地址,函数中的变量
当函数从入口函数main函数开始执行时,编译器会将我们操作系统的运行状态,main函数的返回地址、main的参数、mian函数中的变量、进行依次压栈;
当main函数开始调用func()函数时,编译器此时会将main函数的运行状态进行压栈,再将func()函数的返回地址、func()函数的参数从右到左、func()定义变量依次压栈;
当func()调用f()的时候,编译器此时会将func()函数的运行状态进行压栈,再将的返回地址、f()函数的参数从右到左、f()定义变量依次压栈
从代码的输出结果可以看出,函数f(var1)、f(var2)依次入栈,而后先执行f(var2),再执行f(var1),最后打印整个字符串,将栈中的变量依次弹出,最后主函数返回
C语言函数参数入栈顺序从右到左是为了方便可变参数函数。
[23]C++中将临时变量作为返回值时的处理过程
临时变量,在函数调用过程中是被压到程序进程的栈中的,当函数退出时,临时变量出栈,即临时变量已经被销毁,临时变量占用的内存空间没有被清空,但是可以被分配给其他变量
函数调用结束后,返回值被临时存储到寄存器中,并没有放到堆或栈中,与内存没有关系。当退出函数的时候,临时变量可能被销毁,但是返回值却被放到寄存器中与临时变量的生命周期没有关系
[24]引用是否能实现动态绑定,为什么可以实现?
可以。引用在创建的时候必须初始化,在访问虚函数时,编译器会根据其所绑定的对象类型决定要调用哪个函数。注意只能调用虚函数。
[25]说说C语言和C++的区别
设计思想上:C++是面对对象的编程语言;C语言是面对过程的编程语言。
语法上:C++具有封装、继承和多态三种特性C++相比C,增加多许多类型安全的功能,比如强制类型转换、C++支持范式编程,比如模板类、函数模板等
[26]说说 C++中 struct 和 class 的区别
struct 一般用于描述一个数据结构集合,而 class 是对一个对象数据的封装;struct 中默认的访问控制权限是 public 的,而 class 中默认的访问控制权限是 private 的struct 继承权限是 public 的,而 class 中继承权限是 private 的class 关键字可以用于定义模板参数,就像 typename,而 struct 不能用于定义模板参数,
[27]c++类的加载过程
• 分配空间(Allocation)• 初始化(Initialization) ( 对象的初始化是通过初始化列表来完成,而对象的赋值则才是通过构造函数,或者更准确的说应该是构造函数的实现体。)
[28]说说include头文件的顺序以及双引号""和尖括号<>的区别
区别:(1)尖括号<>的头文件是系统文件,双引号""的头文件是自定义文件。(2)编译器预处理阶段查找头文件的路径不一样。查找路径:(1)使用尖括号<>的头文件的查找路径:编译器设置的头文件路径 --> 系统变量。(2)使用双引号""的头文件的查找路径:当前头文件目录-->编译器设置的头文件路径-->系统变量
[29]说说C++结构体和C结构体的区别(申明5使用1)
(1) C语言的struct不能有成员函数、静态成员,而C++的struct可以有。(2) C语言的struct不能初始化数据成员,而C++的struct可以有(3) C语言的struct中数据成员只有public访问权限的设定,而C++ 的struct的成员有访问权限设定。(4) C语言的struct是没有继承关系的,而C++的struct却有丰富的继承关系。
[30]导入C函数的关键字是什么,C++编译时和C有什么不同?
关键字:在C++中,导入C函数的关键字是extern,表达形式为extern “C”, extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。
编译区别:由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。extern:(1)extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中(2)当C++和C混用时,此时C函数就需要用extern “C”进行链接指定,表示这是C中的函数。
[31]Static
1局部static对象表示其生命周期从定义开始,直到程序运行结束为止
2全局static对象或函数表示其可见范围局限于该文件,即便是 extern 外部声明也不可以。static 修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。
3类的static数据成员表示该数据成员不属于该类对象而属于类本身,所有对象共享该成员,可用类名::数据成员名来访问。类内申明,类外初始化。可以被非static成员函数任意访问。
- 类的static函数成员表示该函数不属于该类对象而属于类本身,可用类名::函数名来访问,在其中只能访问类的静态成员。类内申明,类外初始化。不具有this指针,无法访问类对象的非static成员变量和非static成员函数;不能被声明为const、虚函数和volatile;可以被非static成员函数任意访问。一个静态成员函数只能访问它的参数、类的静态数据成员和全局变量。不能用const的原因:一个静态成员函数访问的值是其参数、静态数据成员和全局变量,而这些数据都不是对象状态的一部分。而对成员函数中使用关键字const是表明:函数不会修改该函数访问的目标对象的数据成员。既然一个静态成员函数根本不访问非静态数据成员,那么就没必要使用const了
static 修饰的变量存放在全局数据区的静态变量区,包括全局静态变量和局部静态变量,都在全局数据区分配内存。初始化的时候自动初始化为 0
类的静态成员函数无法直接访问普通数据成员(可以通过对象名间接的访问),而类的任何成员函数都可以访问类的静态数据成员
外部访问类的静态成员能直接通过类名来访问,虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象、引用或指针来访问静态成员
[32]静态成员与普通成员的区别
- 生命周期 静态成员变量从类被加载开始到类被卸载,一直存在; 普通成员变量只有在类创建对象后才开始存在,对象结束,它的生命期结束;
- 共享方式 静态成员变量是全类共享;普通成员变量是每个对象单独享用的;
- 定义位置 普通成员变量存储在栈或堆中,而静态成员变量存储在静态全局区;
- 初始化位置 普通成员变量在类中初始化;静态成员变量在类外初始化;
- 默认实参 可以使用静态成员变量作为默认实参,
[33]条件编译#define、#ifndef、#ifdef、#endif
防止头文件重复引用
[34]Volatile易挥发,易变的,不优化的
多线程中被几个任务共享的变量需要定义为volatile类型。中断服务程序中修改的供其它程序检测的变量需要加volatile;存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
- 表示易变变量,告诉编译器不要优化该变量,每次需要此变量值时都从内存中访问,不要放到寄存器中优化
- 一个变量可以既是const的也是volatile的,因为const表示程序不应更改它(编译阶段起作用),但它可能被其他因素改变.
- 可 以 ,用 c o n s t 和 v o l a t i l e同 时 修 饰 变 量 , 表 示 这 个 变 量 在 程 序 内 部 是 只 读 的 , 不 能 改 变 的 , 只 在 程 序 外 部 条 件 变 化 下 改 变 , 并 且 编 译 器 不 会 优 化 这 个 变 量 。 每 次 使 用 这 个 变 量 时 , 都 要 小 心 地 去 内 存 读 取 这 个 变 量 的 值 , 而 不 是 去 寄 存 器 读 取 它 的 备 份 。注 意 : 在 此 一 定 要 注 意 c o n s t 的 意 思 , c o n s t 只 是 不 允 许 程 序 中 的 代 码 改 变 某 一 变 量 , 其 在 编 译 期 发 挥 作 用 , 它 并 没 有 实 际 地 禁 止 某 段 内 存 的 读 写 特 性
[35] gcc o1 o2优化选项的区别
gcc默认提供了5级优化选项:-O:无优化(默认)-O1:使用能减少目标文件大小以及执行时间并且不会使编译时间明显增加的优化-O2: 包含-O1的优化,将会花费更多的编译时间当然也会生成性能更好的代码。
[36]const
- 对于变量,阻止一个变量被改变,定义该const变量时,需先初始化
- 对于指针,可以是指针常量,也可以是常量指针
- 对于类的成员函数,表明其是一个常函数,在其中不能修改类的数据成员,但可以修改mutable的数据成员。
- 对于类的const数据成员,在初始化列表中被初始化。
- const对象不可以调用非const成员函数;非const对象都可以调用;const对象只能调用const成员函数。
- const修饰变量是也与static有一样的隐藏作用。只能在该文件中使用,其他文件不可以引用声明使用
- const类型变量必须定义的时候进行初始化,因此也导致如果类的成员变量有const类型的变量,那么该变量必须在类的初始化列表中进行初始化
- 只有引用传递和指针传递可以用是否加const来重载。一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开来。(顶层const不可以,底层const可以)
常函数,就是对类中任何成员不作修改而只能作访问的函数(mutable除外)
常函数,只能访问成员变量,不能修改,(除非在成员变量+mutable,则可以修改)
普通对象和常对象都可以访问常函数 ,常对象只能访问常函数常对象只能调用常函数;静态成员函数只能访问静态成员变量(以及全局变量)。常函数,只能访问成员变量,不能修改,(除非在成员变量+mutable,则可以修改)
[37]C++内存分区模型
[https://blog.csdn.net/newson92/article/details/112385022]C++内存分区模型 四区(代码区、全局区、栈区、堆区)
[38]C++中类的数据成员和成员函数内存分布情况
一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量的地址。
对象的大小和对象中数据成员的大小是一致的,也就是说,成员函数不占用对象的内存。这是因为所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。静态成员函数与一般成员函数的唯一区别就是没有this指针,因此不能访问非静态数据成员
[39]this指针
• this指针是类的指针,指向对象的首地址。• this指针只能在成员函数中使用,在全局函数、静态成员函数中都不能用this。• this指针只有在成员函数中才有定义,且存储位置会因编译器不同有不同存储位置。
this在成员函数的开始执行前构造,在成员的执行结束后清除this指针只有在成员函数中才有定义
[40]在成员函数中调用delete this会出现什么问题?对象还可以使用吗?
在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内容,类的成员函数单独放在代码段中。当调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要不涉及到this指针的内容,都能够正常运行。对象不可以使用。一旦涉及到this指针,如操作数据成员,调用虚函数等,就会出现不可预期的问题
[后续]见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
欢迎关注、收藏、点赞后进行问题咨询及秋招建议!!
#2023毕业生求职有问必答##牛客在线求职答疑中心##牛客解忧铺##如何判断面试是否凉了##晒一晒我的offer#包含C++、操作系统、数据库、计算机组成、计算机网络、设计模式、操作系统、牛客网服务器项目、综合智力题等