C++面试常见问题准备

1、strlen与sizeof的区别:
(1) strlen()是函数,在运行时才能计算。参数必须是字符型指针(char*),且必须是以’\0’结尾的;当数组名作为参数传入时,实际上数组已经退化为指针了。它的功能是返回字符串的长度。
(2) sizeof()是运算符,在编译时就计算好了,用于计算数据空间的字节数。因此,sizeof不能用来返回动态分配的内存空间的大小。sizeof常用于返回类型和静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系。
当参数分别如下时,sizeof返回的值表示的含义如下所述:
1)数组----编译时分配的数组空间大小;
2)指针----存储该指针所用的空间大小;
3)类型----该类型所占的空间大小;
4)对象----对象的实际占用空间大小;
5)函数----函数的返回类型所占的空间大小,且函数的返回类型不能是void。

2、this指针的特点:
1)只能在成员函数中使用,在全局函数,静态成员函数中都不能使用this;
2)this指针是在成员函数的开始前构造,并在成员函数的结束后清除;
3)this指针会因编译器不同而有不同的存储位置,可能是栈、寄存器或全局变量;
4)this是类的指针;
5)因为this指针只有在成员函数中才有定义,所以获得一个对象后,不能通过对象使用this指针,所以也就无法知道一个对象的this指针的位置。不过,可以在成员函数中指定this指针的位置;
6)普通的类函数(不论是非静态成员函数,还是静态成员函数)都不会创建一个函数表来保存函数指针,只有虚函数才会被放到函数表中。

3、继承方式:
1)公用继承:基类的公用成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类私有;
2)私有继承:基类的公用成员和保护成员在派生类中成了私有成员,其私有成员仍为基类私有;
3)受保护的继承:基类的公用成员和保护成员在派生类中成了保护成员,其私有成员仍为基类私有;保护成员的意思是,不能被外界引用,但可以被派生类的成员引用;

4、虚函数的作用:
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数;

5、预处理:生成.i文件
1)将所有的#define删除,并且展开所有的宏定义;
2)处理所有条件预编译指令,比如#if、#ifdef、#elif、#else、#endif;
3)处理#include预编译指令,将被包含的文件插入到该预编译指令的位置;
4)过滤所有的注释“//"和”/**/“中的内容;
5)添加行号和文件名标识;
6)保留所有的#pragma编译器指令;

6、编译:
把预处理完的文件进行一系列的词法分析、语法分析、语义分析以及优化后产生相应的汇编代码文件;
扫描(词法分析)——语法分析——语义分析——源代码优化——代码生成——目标代码优化;

7、链接:
把每个的源代码模块独立地编译,然后按照要求将它们组装起来;
过程包括地址和空间分配、符号决议和重定位等步骤;
编译器将extern声明的变量置入未解决符号表,而不置入导出符号表,这属于外部链接
编译器将static声明的全局变量不置入未解决符号表,也不置入导出符号表,因此其他单元无法使用,这属于内部链接

**静态链接:**对函数库的链接放在编译时期完成;libxxx.a;
**动态链接:**对库函数的链接载入推迟到程序运行使其;libxxxx.so
各自特点:
1)动态链接库有利于进程间资源共享;
内存中如果已有库函数拷贝,则可共享,没有时才链接载入;
静态链接库的话则每个程序都要将库函数拷贝到自己的代码段,占用了更大的内存资源;
2)将一些程序升级变得简单;
库发生变化,使用静态库的程序要重新编译,而使用动态库的程序只要接口没变,则用新生成的动态库替换即可;
3)动态库可以做到在运行时有需求才调入;
4)静态库在编译时已装载好库函数,所以静态库的程序速度更快些;

8、堆和栈的区别:
(1)申请方式不同
1)栈:由系统自动分配;
2)堆:需要程序员自己申请,并指明大小。C中用malloc函数,C++用new运算符;
(2)申请后系统的响应不同
1)栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常,提示栈溢出;
2)堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间中大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。其次,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。最后,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动地将多余的那部分重新放入空闲链表中;
(3)申请大小的限制不同
1)栈:栈是向低地址扩展的数据结构,是一块连续的内存区域,如果申请的空间超过栈的剩余空间时,将提示overflow,因此,能从栈获得的空间较小;
2)堆:堆是向高地址扩展的数据结构,是不连续的内存区域;这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址;堆的大小受限于计算机系统中有效的虚拟内存;由此可见,堆获得的空间比较灵活,也比较大;
(4)申请效率不同
1)栈由系统自动分配,速度较快;但程序员是无法控制的;
2)堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片;不过用起来最方便;
(5)堆和栈中的存储内容不同
1)栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
2)堆:一般是在堆的头部用一个字节存放堆的大小,堆中的具体内容由程序员安排。

猜你喜欢

转载自blog.csdn.net/qq_38224589/article/details/82876474