C++基础知识梳理二

1.隐式类型转换
基本数据类型的转换以低精度到高精度,即保证精度不丢失。如:char 到 int,int 到 long。
自定义对象:子类对象可隐式的转换为父类对象。

发生条件:https://blog.****.net/weixin_40627841/article/details/88320470

2.new/delete和malloc/free的区别
new/delete是C++的关键字,而malloc/free是C语言的库函数,后者使用必须指明申请内存空间的大小,对于类类型的对象,后者不会调用构造函数和析构函数

3.RTTI
运行时类型信息,在C++层面主要体现在dynamic_cast和typeid,VS中虚函数表的-1位置存放了指向type_info的指针。对于存在虚函数的类型,typeid和dynamic_cast都会去查询type_info
https://www.cnblogs.com/jameszhan/p/RTTI.html

4.虚函数表具体是怎样实现运行时多态的
子类若重写父类虚函数,虚函数表中,该函数的地址会被替换,对于存在虚函数的类的对象,在VS中,对象的对象模型的头部存放指向虚函数表的指针,通过该机制实现多态。

5.函数调用,压栈原理
可执行文件代码段中包含的二进制级别的机器代码会被装入内存的代码区(.text),处理器将到内存的这个区域一条一条地取出指令和操作数,并送入运算逻辑单元进行运算;如果代码中请求开辟动态内存,则会在内存的堆区分配一块大小合适的区域返回给代码区的代码使用;当函数调用发生时,函数的调用关系等信息会动态地保存在内存的栈区,以供处理器在执行完被调用函数的代码时,返回母函数
函数调用包括以下步骤:
(1)参数入栈:将参数从右向左依次压入系统栈中。
(2)返回地址入栈:将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行。
(3)代码区跳转:处理器从当前代码区跳转到被调用函数的入口处。
(4)栈帧调整:具体包括:
  <1>保存当前栈帧状态值,已备后面恢复本栈帧时使用(EBP入栈)。
   <2>将当前栈帧切换到新栈帧(将ESP值装入EBP,更新栈帧底部)。
  <3>给新栈帧分配空间(把ESP减去所需空间的大小,抬高栈顶)。
  <4>对于_stdcall调用约定,函数调用时用到的指令序列大致如下:
    push 参数3 ;假设该函数有3个参数,将从右向做依次入栈
    push 参数2
    push 参数1
    call 函数地址 ;call指令将同时完成两项工作:a)向栈中压入当前指令地址的下一个指令地址,即保存返回地址。 b)跳转到所调用函数的入口处。
    push ebp ;保存旧栈帧的底部
    mov ebp,esp ;设置新栈帧的底部 (栈帧切换)
    sub esp,xxx ;设置新栈帧的顶部 (抬高栈顶,为新栈帧开辟空间)
函数返回的步骤如下:
  <1>保存返回值,通常将函数的返回值保存在寄存器EAX中。
  <2>弹出当前帧,恢复上一个栈帧。具体包括:
  (1)在堆栈平衡的基础上,给ESP加上栈帧的大小,降低栈顶,回收当前栈帧的空间。
  (2)将当前栈帧底部保存的前栈帧EBP值弹入EBP寄存器,恢复出上一个栈帧。
  (3)将函数返回地址弹给EIP寄存器。
  <3>跳转:按照函数返回地址跳回母函数中继续执行。
  还是以C语言和Win32平台为例,函数返回时的相关的指令序列如下:
  add esp,xxx ;降低栈顶,回收当前的栈帧
  pop ebp ;将上一个栈帧底部位置恢复到ebp
  retn ;a)弹出当前栈顶元素,即弹出栈帧中的返回地址,至此,栈帧恢复到上一个栈帧工作完成。b)让处理器跳转到弹出的返回地址,恢复调用前代码区
  C++基础知识梳理二
函数栈帧:ESP和EBP之间的内存空间为当前栈帧,EBP标识了当前栈帧的底部,ESP标识了当前栈帧的顶部
  
6.C++中拷贝赋值函数的形参能否进行值传递
不能。如果是这种情况下,调用拷贝构造函数的时候,首先要将实参传递给形参,这个传递的时候又要调用拷贝构造函数。。如此循环,无法完成拷贝,栈也会满

7.静态函数和虚函数的区别
静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销