C/C++ 常见面试题

 

1.指针和引用有什么分别;如果传引用比传指针安全,为什么?如果我使用常量指针难道不行吗?

     (1) 引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化,可以在定义后面的任何地方重新赋值.

     (2) 不存在NULL引用,引用必须与合法的存储单元关联;而指针则可以是NULL.

     (3) 引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以改变为指向另一个对象.
给引用赋值并不是改变它和原始对象的绑定关系.

     (4) 引用的创建和销毁并不会调用类的拷贝构造函数

     (5) 语言层面,引用的用法和对象一样;在二进制层面,引用一般都是通过指针来实现的,只不过编译器帮我们完成了转换.

     不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,显得很安全。

     const 指针仍然存在空指针,并且有可能产生野指针.

     总的来说:引用既具有指针的效率,又具有变量使用的方便性和直观性.


2.构造函数可否是虚汗数,为什么?析构函数呢,可否是纯虚的呢?

     构造函数不能为虚函数,要构造一个对象,必须清楚地知道要构造什么,否则无法构造一个对象。

     析构函数可以为纯虚函数。

3.为什么要引入抽象基类和纯虚函数?

     主要目的是为了实现一种接口的效果。


4. 结构与联合有和区别?

(1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间),
而结构的所有成员都存在(不同成员的存放地址不同)。

(2). 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。


5. #include<file.h> 与 #include "file.h"的区别?

答: 前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h, 如果后者没有找到对应的文件,就按前者的路径去寻找。


6. 面向对象的三个基本特征,并简单叙述之?

   (1). 封装:将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)

   (2). 继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。

   (3). 多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

7. 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?

   从定义上来说:
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
   重写:是指子类重新定义复类虚函数的方法。


8. 什么是预编译,何时需要预编译:总是使用不经常改动的大型代码体。

   程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。

9. 一个由c/C++编译的程序占用的内存分为以下几个部分
(1)、栈区(stack)—      由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小
(2)、堆区(heap) —      一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。。
(3)、全局区(静态数据区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
(4)、文字常量区 —      常量字符串就是放在这里的。 程序结束后由系统释放
(5)、程序代码区 —      存放函数体的二进制代码。

10. new和malloc的区别?
(1)、new 是c++中的操作符,malloc是c 中的一个函数, new可以认为是malloc加构造函数的执行。

(2)、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数

11. 解释下函数指针?
“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。
有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。
int func(int x); /* 声明一个函数 */
int (*f) (int x); /* 声明一个函数指针 */
f=func;           /* 将func函数的首地址赋给指针f */

12. int (*s[10])(int) 表示的是什么?
int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。

13. 进程和线程的区别?
进程是系统进行资源分配和调度的一个独立单位. 进程在执行过程中拥有独立的内存单元,线程是进程的一个实体,是CPU调度和分派的基本单位,
它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,一个进程有多个线程,这些线程共享内存,从而极大地提高了程序的运行效率。

14. 多线程和多进程的区别?
线程执行开销小,但不利于资源管理和保护;而进程正相反.       

       用多进程每个进程有自己的地址空间(address space),线程则共享地址空间。所有其它区别都是由此而来的:

       (1)速度:线程产生的速度快,线程间的通讯快、切换快等,因为他们在同一个地址空间内。

       (2)资源利用率:线程的资源利用率比较好也是因为他们在同一个地址空间内。

       (3)同步问题:线程使用公共变量/内存时需要使用同步机制还是因为他们在同一个地址空间内。


15. 如何判断一个单链表是有环的?(注意不能用标志位,最多只能用两个额外指针)
一种O(n)的办法就是(搞两个指针,一个a每次递增一步,一个b每次递增两步,如果有环的话两者必然重合,反之亦然),因为每次b比a多走一步,和追赶问题一样,总会
追赶上,最多走n步(n为单链表的长度).

16. 用两个栈实现一个队列的功能?要求给出算法和思路!

      设2个栈为A,B, 一开始均为空.

      入队: 将新元素push入栈A;

      出队:

            (1)判断栈B是否为空;

            (2)如果为空,则将栈A中所有元素依次pop出并push到栈B;

            (3)将栈B的栈顶元素pop出;这样实现的队列入队和出队的平摊复杂度都还是O(1)


17. 缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上,
void function(char *str) {
char buffer[16];
strcpy(buffer,str);
}
上面的strcpy()将直接吧str中的内容copy到buffer中。这样只要str的长度大于16,就会造成buffer的溢出,使程序运行出错。存在象strcpy这样的问题的标准函数还有strcat(),sprintf(),vsprintf(),gets(),scanf()等。

18.全局变量和静态变量的区别?  
   全局变量和静态全局变量的区别在于作用域不同,一个项目里如果有多个源程序文件非静态全局变量可以在所有源文件里调用,静态全局变量只能在本文件里调用,不允许在其他文件里调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值