Skip to content

Latest commit

 

History

History
78 lines (39 loc) · 6.24 KB

c:c++八股.md

File metadata and controls

78 lines (39 loc) · 6.24 KB

设计模式

创建型模式5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

c/c++八股

面向对象:继承、封装、多态。

预编译:将头文件编译,进行宏替换,输出.i文件

编译:将其转化为汇编语言文件,主要做词法分析,语义分析以及检查错误,检查无误后将代码翻译成汇编语言,生成.s文件

汇编:汇编器将汇编语言文件翻译成机器语言,生成.o文件

链接:将目标文件和库链接到一起,生成可执行文件.exe

虚函数:用于实现多态

析构函数⼀般写成虚函数的原因:是为了降低内存泄漏的可能性。

仅执⾏基类的析构,派⽣类的⾃身内容将⽆法被析构,造成内存泄漏。

如果基类的析构函数定义成虚函数,那么编译器就可以根据实际对象,执⾏派⽣类的析构函数,再执⾏基类的析构函数,成功释放内存。

重载:翻译自 overload,是指同一可访问区内被声明的几个具有不同参数列表的同名函数,依赖于 C++函数名字的修饰 会将参数加在后面,可以是参数类型,个数,顺序的不同。根据参数列表决定调用哪个函数,􏰀载不关心函数的返 回类型。

重写:翻译自 override,派生类中􏰀新定义父类中除了函数体外完全相同的虚函数,注意被􏰀写的函数不能是 static 的, 一定要是虚函数,且其他一定要完全相同。要注意,􏰀写和被􏰀写的函数是在不同的类当中的,􏰀写函数的访问修 饰符是可以不同的,尽管 virtual 中是 private 的,派生类中􏰀写可以改为 public。

重定义(隐藏):派生类􏰀新定义父类中相同名字的非 virtual 函数,参数列表 和返回类型都可以不同,即父类中除了定义成 virtual 且完全相同的同名函数才 不会被派生类中的同名函数所隐藏(􏰀定义)。

锁的底层原理是什么 锁的底层是通过CAS,atomic 机制实现。

CAS机制:全称为Compare And Swap(比较相同再交换)可以将比较和交换操作转换为原子操作,CAS操作依赖于三个值:内存中的值V,旧的预估值X,要修改的新值B,如果旧的预估值X等于内存中的值V,就将新的值B保存在内存之中。(就是每一个线程从主内存复制一个变量副本后,进行操作,然后对其进行修改,修改完后,再刷新回主内存前。再取一次主内存的值,看拿到的主内存的新值与当初保存的快照值,是否一样,如果不一样,说明有其他线程修改,本次修改放弃,重试。)

volatile 三个特性

易变性:在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的 volatile 变􏰁的寄存器 内容,而是􏰀新从内存中读取。

不可优化性:volatile 告诉编译器,不要对我这个变􏰁进行各种激进的优化,甚至将变􏰁直接消除,保证程序员写 在代码中的指令,一定会被执行。

顺序性:能够保证 volatile 变􏰁之间的顺序性,编译器不会进行乱序优化。

extern

在 C 语言中,修饰符 extern 用在变􏰁或者函数的声明前,用来说明 “此变􏰁/函数是在别处定义的,要在此处引 用”。

注意 extern 声明的位置对其作用域也有关系,如果是在 main 函数中进行声明的,则只能在 main 函数中调用,在 其它函数中不能调用。其实要调用其它文件中的函数和变􏰁,只需把该文件用 #include 包含进来即可,为啥要用 extern?因为用 extern 会加速程序的编译过程,这样能节省时间。

在 C++ 中 extern 还有另外一种作用,用于指示 C 或者 C++函数的调用规范。比如在 C++ 中调用 C 库函数,就 需要在 C++ 程序中用 extern “C” 声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C 函数规范 来链接。主要原因是 C++ 和 C 程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题。

基类的析构函数写为虚函数的影响

  1. 确保正确的析构行为

    • 当你通过基类指针或引用删除一个派生类对象时,如果基类的析构函数不是虚函数,则只会调用基类的析构函数,而不会调用派生类的析构函数。这样可能导致派生类中资源未能正确释放,造成资源泄漏。
    • 将基类的析构函数声明为虚函数后,通过基类指针或引用删除对象时,会正确调用派生类的析构函数,然后再调用基类的析构函数,保证了对象完整的析构过程。
  2. 多态支持

    • 虚析构函数是多态性的一个重要组成部分。它允许在运行时根据对象的实际类型调用正确的析构函数,从而实现动态绑定。
  3. 性能影响:声明虚函数会引入一些性能开销,因为编译器需要维护一个虚函数表(vtable)以支持动态绑定。不过,在大多数情况下,这种开销是可以忽略不计的,尤其是与确保正确的资源管理相比。

  4. 基类设计:通常,只有当一个类被设计成用于继承并且通过基类指针或引用操作时,才需要将析构函数声明为虚函数。

  5. 补:

    构造函数不能为虚函数,虚函数的调用是通过虚函数表来查找的,而虚函数表由类的实例化对象的vptr指针指向,该指针存放在对象的内部空间之中,需要调用构造函数完成初始化,如果构造函数为虚函数,那么调用构造函数就需要去寻找vptr,但此时vptr还没有完成初始化,导致无法构造对象。

    析构函数可以且经常为虚函数:当我们使用父类指针指向子类时,只会调用父类的析构函数,子类的析构函数不会被调用,容易造成内存泄漏。