面经总结|秋招面经总结 —— C++ 篇(一)|2021 |
41811
2020.11.30
2020.12.10
发布于 未知归属地

0f3c2d459d07e245b4439a8ce2159099.png

写在前面

该系列是笔者总结的 C++ 语言方面的一些面经,由于涉及的知识点比较多,笔者将分为几个部分进行总结,更新目录及链接:

🔗 2021 秋招面经总结 —— C++ 篇(一)
🔗 2021 秋招面经总结 —— C++ 篇(二)


当然只看总结好的面经并不一定能够完全理解其中的知识点,建议看到不懂的地方查阅下《C++Primer》这本书。这本书内容十分全面,但是也比较厚,可以作为一本工具书来看,如果从头到尾看下来可能比较耗时间,推荐的做法是抽取其中的一部分知识点来看,边看边总结。笔者当时是从头到尾看了一遍,极为不推荐这种方式,因为重难点内容往往静不下心来看。

C++ 程序的编译过程(源码如何转化成二进制)

参考链接: 🔗 这里

编译过程分为四个过程:编译(编译预处理、编译、优化),汇编,链接

  • 编译预处理:处理以 # 开头的指令
  • 编译、优化:将源码 .cpp 文件翻译成 .s 汇编代码
  • 汇编:将汇编代码 .s 翻译成机器指令 .o 文件
  • 链接:汇编程序生成的目标文件并不会立即执行,可能有源文件中的函数引用了另一个源文件中定义的符号或者调用了某个库文件中的函数。那链接的目的就是将这些目标文件连接成一个整体,从而生成可执行的程序 .exe 文件。
    在这里插入图片描述

链接分为两种:
参考链接: 🔗 这里

  • 静态链接:代码从其所在的动态链接库中拷贝到最终的可执行程序中,在该程序被执行时,这些代码会被装入到该进程的虚拟地址空间中
  • 动态链接:代码被放到动态链接库或共享对象的某个目标文件中,链接程序只是在最终的可执行程序中记录了共享对象的名字等一些信息。在程序执行时,动态链接库的全部内容会被映射到运行时相应进行的虚拟地址的空间

二者的优缺点:

  • 静态链接 浪费空间,每个可执行程序都会有目标文件的一个副本,这样如果目标文件进行了更新操作,就需要重新进行编译链接生成可执行程序(更新困难);优点就是执行的时候运行速度快,因为可执行程序具备了程序运行的所有内容
  • 动态链接:节省内存、更新方便,但是动态链接是在程序运行时,每次执行都需要进行链接,性能会有一定的损失。

指针和引用的区别

  • 指针所指向的内存空间在程序运行过程中可以改变,而引用所绑定的对象一旦绑定就不能改变。(是否可变)
  • 指针本身在内存中占有内存空间,引用相当于变量的别名,在内存中不占内存空间(是否占内存)
  • 指针可以为空,但是引用必须绑定对象(是否可为空)
  • 指针可以有多级,但是引用只能一级(是否能为多级)

堆和栈的区别

  • 申请方式:栈是系统自动分配,堆是程序员主动申请
  • 申请后系统响应:分配栈空间,如果剩余空间大于申请空间则分配成功,否则分配失败栈溢出;申请堆空间,堆在内存中呈现的方式类似于链表(记录空闲地址空间的链表),在链表上寻找第一个大于申请空间的节点分配给程序,将该节点从链表中删除,大多数系统中该块空间的首地址存放的是本次分配空间的大小,便于释放,将该块空间上的剩余空间再次连接在空闲链表上
  • 栈在内存中是连续的一块空间(向低地址扩展)最大容量是系统预定好的,堆在内存中的空间(向高地址扩展)是不连续的
  • 申请效率:栈是有系统自动分配,申请效率高,但程序员无法控制;堆是由程序员主动申请,效率低,使用起来方便但是容易产生碎片
  • 存放的内容:栈中存放的是局部变量,函数的参数;堆中存放的内容由程序员控制

new 和 delete 是如何实现的,new 与 malloc 的异同处

在使用的时候 new,delete 搭配使用,malloc 和 free 搭配使用。

  • 属性:malloc/free 是库函数,需要头文件的支持;new/delete 是关键字,需要编译器的支持
  • 参数:new 申请空间时,无需指定分配空间的大小,编译器会根据类型自行计算;malloc 在申请空间时,需要确定所申请空间的大小
  • 返回值:new 申请空间时,返回的类型是对象的指针类型,无需强制类型转换,符合类型安全的操作符;malloc 申请空间时,返回的是 void* 类型,需要进行强制类型的转换,转换为对象类型的指针
  • 分配失败:new 分配失败时,会抛出 bad_alloc 异常,malloc 分配失败时返回空指针
  • 重载:new/delete 支持重载,malloc/free 不能进行重载
  • 自定义类型实现:new 首先调用 operator new 函数申请空间(底层通过 malloc 实现),然后调用构造函数进行初始化,最后返回自定义类型的指针;delete 首先调用析构函数,然后调用 operator delete 释放空间(底层通过 free 实现)。malloc/free 无法进行自定义类型的对象的构造和析构
  • 内存区域:new 操作符从自由存储区上为对象动态分配内存,而 malloc 函数从堆上动态分配内存。(自由存储区不等于堆)

C 和 C++ 的区别

  • C 是面向过程的编程,特点是函数;C++ 是面向对象的编程,特点是类。(特性)
  • C 主要用在嵌入式开发、驱动开发和硬件直接打交道的领域;C++ 可以用于应用层的开发、用户界面开发等和操作系统直接打交道的领域。(应用领域)
  • C++ 继承了C的底层操作特性,增加了面向对象的机制,增加了泛型编程、异常处理、运算符重载,还增加了命名空间,避免了命名冲突。(相较于 C 的升级)

C++、Java 的联系与区别,包括语言特性、垃圾回收、应用场景等(java 的垃圾回收机制)

参考链接
二者在语言特性上有很大的区别:

  • 指针:C++ 可以直接操作指针,容易产生内存泄漏以及非法指针引用的问题;JAVA 并不是没有指针,虚拟机(JVM)内部还是使用了指针,只是编程人员不能直接使用指针,不能通过指针来直接访问内存,并且 JAVA 增加了内存管理机制
  • 多重继承:C++ 支持多重继承,允许多个父类派生一个类,虽然功能很强大,但是如果使用的不当会造成很多问题,例如:菱形继承;JAVA 不支持多重继承,但允许一个类可以继承多个接口,可以实现 C++ 多重继承的功能,但又避免了多重继承带来的许多不便
  • 数据类型和类:C++ 可以将变量或函数定义成全局,但是JAVA是完全面向对象的语言,除了基本的数据类型之外,其他的都作为类的对象,包括数组。

垃圾回收:

  • JAVA 语言一个显著的特点就是垃圾回收机制,编程人员无需考虑内存管理的问题,可以有效的防止内存泄漏,有效的使用空闲的内存
  • JAVA 所有的对象都是用 new 操作符建立在内存堆栈上,类似于 C++ 中的 new 操作符,但是当要释放该申请的内存空间时,JAVA 自动进行内存回收操作,C++ 需要程序员自己释放内存空间,并且 JAVA 中的内存回收是以线程的方式在后台运行的,利用空闲时间。

应用场景:

  • java 运行在虚拟机上,和开发平台无关,C++ 直接编译成可执行文件,是否跨平台在于用到的编译器的特性是否有多平台的支持,
  • C++ 可以直接编译成可执行文件,运行效率比 JAVA 高
  • JAVA 主要用来开发 web 应用
  • C++ 主要用在嵌入式开发、网络、并发编程的方面

Struct 和 class 的区别

参考链接:https://blog.csdn.net/bestconvenient/article/details/30734139
struct 和 class 都可以自定义数据类型,也支持继承操作

  • struct 中默认的访问级别是 public,默认的继承级别也是 public
  • class 中默认的访问级别是 private,默认的继承级别也是 private
  • 当 class 继承 struct 或者 struct 继承 class 时,默认的继承级别取决于默认的继承级别取决于class或struct本身, class(private 继承) ,struct(public 继承)
C++
struct A{}class B : A{}; //private继承
struct C : B{}//public继承

举例:

C++
#include<bits/stdc++.h>

using namespace std;

class A{
public:
    void printA(){
        cout << "class A" << endl;
    }
};

struct B: A{//由于 B 是 struct,A的继承级别为 public(取决于B的默认继承级别)
public:
    void printB(){
        cout << "class B" << endl;
    }
};

class C: B{//由于 C 是 class,B的继承级别为 private(取决于C的默认继承级别),所以无法访问基类B中的printB函数

};

int main(){
    A ex1;
    ex1.printA(); // class A

    B ex2;
    ex2.printA(); // class A
    ex2.printB(); // class B

    C ex3;
    ex3.printB(); // error: 'B' is not an accessible base of 'C'
    return 0;
}
  • class 可以使用模板,struct 不能

define 和 const 的区别(编译阶段、安全性、内存占用等)

  • 编译阶段:define 是在编译预处理阶段起作用,const 是在编译阶段和程序运行阶段起作用
  • 安全性:define 定义的宏常量没有数据类型,只是进行简单的替换,不会进行类型安全的检查;const 定义的只读变量是有类型的,是要进行判断的,可以避免一些低级的错误
  • 内存占用:define 定义的宏常量,在程序中使用多少次就会进行多少次替换,内存中有多个备份;const 定义的只读变量在程序运行过程中只有一份
  • 调试:define 定义的不能调试,因为在预编译阶段就已经进行替换了;const 定义的可以进行调试

const 的优点:

  • 有数据类型,在定义式可进行安全性检查
  • 可调式
  • 占用较少的空间

在 C++ 中 const 和 static 的用法(定义,用途)

const 参考 🔗 这里

  • const 修饰成员变量,定义成 const 常量,相较于宏常量,可进行类型检查,节省内存空间,提高了效率
  • const 修饰函数参数,使得传递过来的函数参数的值不能改变
  • const 修饰成员函数,使得成员函数不能修改任何类型的成员变量(mutable 修饰的变量除外,函数参数也除外),也不能调用非 const 成员函数,因为非 const 成员函数可能会修改成员变量

static 定义静态变量,静态函数

  • static 作用于局部变量,改变了局部变量的生存周期,使得该变量存在于定义后直到程序运行结束的这段时间
  • static 作用于全局变量和函数,改变了全局变量的作用域,使得全局变量只能在定义它的文件中使用,在源文件中不具有全局可见性
  • static 作用于类的成员变量和类的成员函数,使得类变量或者类成员函数和类有关,也就是说可以不定义类的对象就可以通过类访问这些静态成员。注意:类的静态成员函数中只能访问静态成员变量或者静态成员函数,不能将静态成员函数定义成虚函数

const 和 static 在类中使用的注意事项(定义、初始化和使用)

参考 🔗 这里

static 静态成员变量:

  1. 静态成员变量是在类内进行声明,在类外进行定义和初始化,在类外进行定义和初始化的时候不要出现 static 关键字和 private/public/protected 访问规则。
  2. 静态成员变量相当于类域中的全局变量,被类的所有对象所共享,包括派生类的对象。
  3. 静态成员变量可以作为成员函数的参数可选参数,而普通成员变量不可以
C++
class base{ 
public : 
    static int _staticVar; 
    int _var; 
    void foo1(int i=_staticVar);//正确,_staticVar为静态数据成员 
    void foo2(int i=_var);//错误,_var为普通数据成员 
};
  1. 静态数据成员的类型可以是所属类的类型,而普通数据成员不可以,普通数据成员只可能声明成类的指针或引用
C++
class base{ 
public : 
    static base _object1;//正确,静态数据成员 
    base _object2;//错误 
    base *pObject;//正确,指针 
    base &mObject;//正确,引用 
};

static 静态成员函数:

  1. 静态成员函数不能调用非静态成员变量或者非静态成员函数,因为静态成员函数没有 this 指针。静态成员函数做为类作用域的全局函数
  2. 静态成员函数不能声明成虚函数(virtual)、const、volatile

const 成员变量

  1. const 成员变量只能在类内声明、定义,在构造函数初始化列表中初始化
  2. const 成员变量只在某个对象的生存周期内是常量,对于整个类而言却是可变的,因为类可以创建多个对象,不同类的 const 成员变量的值是不同的,所以不能在类的声明中初始化 const 成员变量,因为类的对象还没有创建,编译器不知道他的值

const 成员函数

  1. 不能修改成员变量的值,除非有 mutable 修饰;只能访问成员变量
  2. 不能调用非常量成员函数,以防修改成员变量的值

const static
如果要想成员变量在整个类中都是恒定的常量,应该用类的枚举常量或者 static const.
在类中进行声明,在类外进行初始化(类似于类的静态常量)

C++ 中的 const 类成员函数(用法和意义)

用法:如上
意义:防止修改成员变量


写在最后

本篇重点总结:

  • 编译过程
  • new delete , free malloc 区别和联系
  • C++ 和 C 的区别
  • C++ 和 Java 的区别
  • struct class 区别
  • define const 区别
  • const static 用法和作用

建议以该大纲复习回顾,后续笔者会继续整理出 C++ 面试中涉及的一些相关知识,也是笔者在面试的过程中被问到的,作为鼓励,大家看完记得点赞或收藏哦!有问题可以在评论区讨论,笔者看到会回复哒~~~~~

评论 (23)