互联网笔试面试经典问题

上传人:第*** 文档编号:33922177 上传时间:2018-02-19 格式:DOCX 页数:7 大小:31.53KB
返回 下载 相关 举报
互联网笔试面试经典问题_第1页
第1页 / 共7页
互联网笔试面试经典问题_第2页
第2页 / 共7页
互联网笔试面试经典问题_第3页
第3页 / 共7页
互联网笔试面试经典问题_第4页
第4页 / 共7页
互联网笔试面试经典问题_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《互联网笔试面试经典问题》由会员分享,可在线阅读,更多相关《互联网笔试面试经典问题(7页珍藏版)》请在金锄头文库上搜索。

1、1const 和#define 的区别:( c+定义常量的方式)1. 编译器处理方式不同define 宏是在预处理阶段展开。const 常量是编译运行阶段使用。2. 类型和安全检查不同define 宏没有类型,不做任何类型检查,仅仅是展开。const 常量有具体的类型,在编译阶段会执行类型检查。3. 存储方式不同define 宏定义不占内存const 常量占用内存(可以是堆中也可以是栈中)。4. const 常量有适当的作用域,而宏常量的作用域是全局的,也就是说宏常量不具有封装性。5. const 常量可以取地址,宏常量不可以取地址。const 作用在 c+中,const 是类型修饰符。1.

2、使用 const 修饰的变量,值不能被更改;2. const 还可以修饰函数参数、函数返回值和函数本身;3. 函数可以根据是否为 const 进行重载;类中 const 成员初始化:在初始化列表中初始化。static 作用static 用来控制变量的存储方式和可见性。1. static 变量存储在程序的静态存储区。(函数执行结束不会释放存储空间)2. static 把变量的可见范围限制在编译单元中,使它成为一个内部链接。总结:static 总是使得变量或对象的存储形式变成静态存储,链接方式变成内部链接。对于局部变量(已经是内部链接了),它仅改变其存储方式;对于全局变量(已经是静态存储了),它仅

3、改变其链接类型。类中的 static 成员:( static 数据成员、static 成员函数)static 成员和类相关,而不是和类的对象相关。项目中有没有用过 static?全局变量、静态全局变量、静态局部变量:当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用它。 (把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。 )static 成员初始化:static 成员必须在类定义体的外部定义,而且应该在定义时初

4、始化。但是,整形 const static 数据成员就可以在类的定义体中进行初始化。函数局部 static 变量初始化:2c+中,在第一次用到时才会被初始化(lazy initialization)。全局 static 变量的初始化在编译的时候进行。extern 关键字:C 和 C+对函数的处理方式( 名称修饰) 是不同的.extern C是使 C+能够调用 C 写作的库文件的一个手段,如果要对编译器提示使用 C 的方式来处理函数的话,那么就要使用extern C来说明。名称修饰防止命名冲突,比如重载函数,不同类中的同名变量等。volatile 关键字:volatile 的本意是“易变的”,

5、用它声明的类型变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。关键字 volatile 是给编译器的指示,指出对这样的对象不应该执行优化。volatile 基本可以做到两件事情:1. 阻止编译器为了提高速度将一个变量缓存到寄存器内而不写回。2. 阻止编译器调整操作 volatile 变量的指令顺序。模板和宏的区别:1. 模板是类型安全的,宏不是。(编译器对模板进行类型安全检查)2. 宏在预编译阶段直接展开,而模板编译后,只有在用到时才实例化。(C+模板的一个特殊的机制:模板中的代码只有在用到时才会被实例化。编译器并不会完全展开整个模板类。只有当访问了模板上的某个成员函

6、数时,才会将成员函数的代码展开作语义检查。)3. 模板的功能更加强大,支持偏特化、支持模板元编程。C+ 设计了模板,设计了常量,设计了内联函数,居然还没有把宏给枪毙掉,真是个笑话。宏:优点:减少函数调用的开销。缺点:没有类型检查,debug 困难( 由于宏是由预处理器扩展的,因此编译器错误消息将引用扩展的宏,而不是宏定义本身。 此外,在调试过程中,宏将以扩展形式出现。)模板缺点:1. 模板是一种编译期间生成代码的行为,无法进行断点调试,所以很容易产生 bug;2. 大量使用模板会造成代码空间膨胀,极大的延长了编译时间。宏和内联函数:内联函数有类型检查。宏定义是预处理器在代码优化时直接替换的,而

7、内联函数是在编译期间插入代码. 宏定义替换比内联函数执行得早。指针和引用的区别:1. 指针是一个实体,在逻辑上是独立的;引用是个别名,在逻辑上不是独立的2. 指针可以为空,引用不可以为空3. 引用需要初始化,指针不需要4. 指针可以被重新赋值,而引用总是指向最初的对象3(引用在语言内部是用指针实现的,引用就是一个常量指针,当然也占内存)C 中指针和引用的物理实现是一回事,都是内存地址;两者的区别是在编译时编译器无法对指针操作进行类型检查,而对引用可以。这也是引用更安全的原因。引用是类型安全的,而指针不是引用传递与指针传递的区别?指针传递参数的本质是值传递,引用的任何操作都处理成间接寻址(指针传

8、值,引用传地址)堆和栈的区别:http:/ 即”向上生长”),是不连续的内存区域。这是由于系统用链表来存储空闲内存地址,自然不连续,而链表从低地址向高地址遍历。空间大小:栈顶地址和栈的最大容量由系统预先规定(通常默认 2M 或 10M);堆的大小则受限于计算机系统中有效的虚拟内存,32 位 Linux 系统中堆内存可达 2.9G 空间。存储内容:栈在函数调用时,首先压入主调函数中下条指令(函数调用语句的下条可执行语句) 的地址,然后是函数实参,然后是被调函数的局部变量。本次调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的指令地址,程序由该点继续运行下条可执行语句。堆通常在头部

9、用一个字节存放其大小,堆用于存储生存期与函数调用无关的数据,具体内容由程序员安排。分配方式:栈可静态分配或动态分配。静态分配由编译器完成,如局部变量的分配。动态分配由 alloca 函数在栈上申请空间,用完后自动释放。堆只能动态分配且手工释放。分配效率:栈由计算机底层提供支持:分配专门的寄存器存放栈地址,压栈出栈由专门的指令执行,因此效率较高。堆由函数库提供,机制复杂,效率比栈低得多。Windows 系统中VirtualAlloc 可直接在进程地址空间中分配一块内存,快速且灵活。分配后系统响应:只要栈剩余空间大于所申请空间,系统将为程序提供内存,否则报告异常提示栈溢出。操作系统为堆维护一个记录

10、空闲内存地址的链表。当系统收到程序的内存分配申请时,会遍历该链表寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点空间分配给程序。若无足够大小的空间(可能由于内存碎片太多 ),有可能调用系统功能去增加程序数据段的内存空间,以便有机会分到足够大小的内存,然后进行返回。,大多数系统会在该内存空间首地址处记录本次分配的内存大小,供后续的释放函数(如 free/delete)正确释放本内存空间。此外,由于找到的堆结点大小不一定正好等于申请的大小,系统会自动将多余的部分重新放入空闲链表中。碎片问题:栈不会存在碎片问题,因为栈是先进后出的队列,内存块弹出栈之前,在其上面的后

11、进的栈内容已弹出。而频繁申请释放操作会造成堆内存空间的不连续,从而造成大量碎片,使程序效率降低。可见,堆容易造成内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和内核态切换,内存申请的代价更为昂贵。所以栈在程序中应用最广泛,函数调用也利用栈来4完成,调用过程中的参数、返回地址、栈基指针和局部变量等都采用栈的方式存放。所以,建议尽量使用栈,仅在分配大量或大块内存空间时使用堆。使用栈和堆时应避免越界发生,否则可能程序崩溃或破坏程序堆、栈结构,产生意想不到的后果。栈中存放的内容:1. 函数参数、函数返回地址2. 函数局部变量3. 上下文:比如函数调用前后需要保证不变的寄存器值memcp

12、y 和 memmove 函数的区别?void * memcpy (void * dest, const void *src, size_t n);void * memmove(void *dest, const void *src, size_t n);作用都是从源内存拷贝 n 个字节到目标内存。不同的是,当源内存和目标内存发生重叠时,memcpy 会出现错误,而 memmove 能正确地实施拷贝,但这也增加了一点点开销。new/delete 和 malloc/free 的区别:1. malloc 是标准库函数,new 是 c+运算符,它们都可用于申请动态内存。2. 对于非内部数据类型的对象而

13、言,对象在创建的同时要自动执行构造函数。malloc 无法满足要求,而 new 可以完成动态内存分配和初始化工作。3. new 自动计算需要分配的空间,而 malloc 需要手工计算。malloc 返回值的类型为 void*,需要显式进行类型转换, new 不需要。4. new 是类型安全的,而 malloc 不是。 5. new 在实现上其实调用了 malloc 函数。1、new 自动计算需要分配的空间,而 malloc 需要手工计算字节数2、new 是类型安全的,而 malloc 不是,比如:int* p = new float2; / 编译时指出错误int* p = malloc(2*s

14、izeof(float); / 编译时无法指出错误new operator 由两步构成,分别是 operator new 和 construct3、operator new 对应于 malloc,但 operator new 可以重载,可以自定义内存分配策略,甚至不做内存分配,甚至分配到非内存设备上。而 malloc 无能为力4、new 将调用 constructor,而 malloc 不能;delete 将调用 destructor,而 free 不能。5、malloc/free 要库文件支持, new/delete 则不要。 如何检测内存泄露:1. vs 下使用 CRT 库函数,或者第三方

15、检测工具 VisualLeakDetector/2. linux 下使用 valgrind。重载(overload)、覆盖(override) = 重写、隐藏(hide)的区别:重载:1. 相同作用域(在同一个类中) ;2. 名字相同;3. 形参表不同;覆盖:(派生类函数重写基类函数)1. 不同作用域(分别位于基类与派生类) ;52. 名字相同;3. 形参表相同、返回值相同;4. 基类函数必须有 virtual 关键字;隐藏:(派生类函数屏蔽基类函数)1. 派生类函数与基类函数名字相同、形参表不同,不论有无 virtual 关键字,基类函数将被隐藏。2. 派生类函数与基类函数名字相同、形参表相

16、同,但是基类函数无 virtual 关键字,基类函数将被隐藏。深拷贝(deep copy)与浅拷贝(shallow copy)的区别:如果一个对象拥有资源,复制对象时连同对象拥有的资源一起复制,就是深拷贝,没有复制对象拥有的资源就是浅拷贝。浅拷贝也称位拷贝。默认的拷贝构造函数和赋值操作符进行的都是浅拷贝。浅拷贝缺点:多个对象指向一块内存,当某个对象释放内存后,其他指向这块内存的对象就会出错。当数据成员中有指针时,必须使用深拷贝。数组、链表、hash 的区别:1. 数组中的元素在内存中是连续存储的,链表中的元素在内存中不是连续存储的。数组支持随机存取,查找效率高,但插入、删除效率低。链表查找效率低,但插入、删除效率高。2. 数组

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文 > 毕业论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号