C++面试突击(1)
1、C++程序的编译过程?
分析:考察你对“程序代码如何变成机器可执行文件”的理解。编译的过程有四个阶段:预处理、编译、汇编、连接。其中宏是在预处理阶段起作用的,即处理以 # 开头的指令,常见的问题有“如何避免头文件被重复包含?”,答案是使用#ifndef/#define/#endif. 编译就是把cpp文件翻译成汇编代码,汇编时再把汇编代码翻译成机器指令;链接就是处理这个cpp文件中调用了其他cpp文件的情况,使文件里的东西可以连接成功,生成可执行的程序。
2、C++内存管理?
分析:面试官最希望听到你描述内存的布局情况。一个C++程序在内存中的区域有几个部分:栈(stack)、堆(heap)、全局/静态存储区、常量存储区、代码区。
函数参量、局部变量、函数返回地址等,是存放在栈里的,这部分的内存由编译器自动管理,即自动分配和释放,特点是速度快,大小有限。
动态分配的内存是存放在堆里的,这部分需要手动管理,特点是空间大,易产生碎片,用自定义内存池(预先分配一大块内存,自己管理)可以规避内存碎片问题。
全局变量和静态变量(static)是存放在全局/静态存储区,程序开始时分配,结束时释放,所以其声明周期是程序运行期间。
常量、被const修饰的全局变量是存放在常量存储区中,这个是只能读的,存在flash中,适合保存不需要更改的参数。
编译后的机器指令是存放在代码区,同样是只读,存在flash里。
3、堆和栈的区别?
分析:栈是由编译器自动管理的,高效但容量小;堆是程序员手动控制的,容量大但管理复杂。“如何避免栈溢出”是绕不开的问题,方法是使用静态或堆分配,替代大局部变量,同时控制递归深度。使用堆如何避免内存泄露也是绕不开的问题,方法上面第2个问题也讲过,使用自定义内存池,预先分配一大块内存,便于自己管理。
4、什么是内存对齐?内存对齐的原则?为什么要进行内存对齐,有什么优点?
分析:内存对齐的是指数据在内存中的存储地址必须满足其大小的整数倍,这也是原则。内存对齐的目的是为了优化CPU访问内存的效率,现代的CPU都是以固定大小的块(如4字节、8字节)来读取内存,专业叫法是内存访问粒度。想象一下不对齐的话会怎样?一个数据可能要放多多次,然后拼接起来!这样效率就大大降低了。
5、智能指针是什么?有几种?实现原理?
分析:智能指针是C++中用于自动管理内存的类模板,在对象生命周期结束时自动释放所管理的内存,可以避免内存泄露和悬空指针的问题。有unique_ptr、shared_ptr、weak_ptr三种。unique_ptr没有额外开销,适用嵌入式系统,代替new/delete组合;shared_ptr可以使多个对象共享同一资源,通过引用计数管理生命周期,引用计数为0时自动释放资源;weak_ptr用于观察shared_ptr管理的资源,解决shared_ptr循环引用的问题,因为共享指针如果相互引用,计数就没办法到0,所以这也是使用智能指针可能会出现的问题。