iPhone软件开发面试题(2)

学人智库 时间:2018-02-10 我要投稿
【www.unjs.com - 学人智库】

  11.关键字volatile有什么含意?并给出三个不同的例子。

  一个定义为 volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

  下面是volatile变量的几个例子:

  并行设备的硬件寄存器(如:状态寄存器)

  一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

  多线程应用中被几个任务共享的变量

  12.一个参数既可以是const还可以是volatile吗?解释为什么。一个指针可以是volatile 吗?解释为什么。

  下面是答案:

  一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

  尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

  13.为什么标准头文件都有类似以下的结构?

  #ifndef __INCvxWorksh

  #define __INCvxWorksh

  #ifdef __cplusplus

  extern "C"

  {

  #endif

  /*...*/

  #ifdef__cplusplus

  }

  #endif

  #endif /* __INCvxWorksh */

  显然,头文件中的编译宏 “#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止该头文件被重复引用。

  14.#import 跟#include的区别,@class呢?

  @class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import

  而#import比起#include的好处就是不会引起交叉编译

  15.MVC 模式的理解

  MVC设计模式考虑三种对象:模型对象、视图对象和控制器对象。

  模型对象代表特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。

  视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。

  控制器对象是应用程序的视图对象和模型对象之间的协调者。

  16. 线程与进程的区别和联系?

  进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。

  进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

  17.列举几种进程的同步机制,并比较其优缺点。

  答案:原子操作;信号量机制;自旋锁;管程;会合;分布式系统 ?

  18.进程之间通信的途径

  答案:共享存储系统消息传递系统管道,以文件系统为基础 ?

  19.进程死锁的原因

  答案:资源竞争及进程推进顺序非法 ?

  20.死锁的4个必要条件

  答案:互斥;请求保持;不可剥夺;环路 ?

  21.死锁的处理

  答案:鸵鸟策略;预防策略;避免策略;检测与解除死锁

  22.堆和栈的区别

  管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

  申请大小: 栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow。因此,能从栈获得的空间较小。?堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

  碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。

  分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由 alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

  分配效率:栈是机器系统提 供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C 函数库提供的,它的机制是很复杂的。

  23.什么是键-值,键路径是什么

  模型的性质是通过一个简单的键(通常是个字符串)来指定的。视图和控制器通过键 来查找相应的属性值。在一个给定的实体中,同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制。

  键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性 质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型?实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。

  For example, the key path address.streetwouldget the value of the address property from the receiving

  object, and then determine the streetproperty relative to the address object.

  24.c和obj-c 如何混用

  1)obj-c的编译器处理 后缀为m的文件时,可以识别obj-c和c的代码, 处理mm文件可以识别obj-c,c,c 代码,但cpp文件必须只能用c/c 代码,而且cpp文件include的头文件中,也不能出现obj- c的代码,因为cpp只是cpp?

  2) 在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是问题?

  3)在cpp中混用obj- c其实就是使用obj-c编写的模块是我们想要的。?

  如果模块以类实现,那么要按照cpp class的标准写类的定义,头文件中不能出现obj-c的东西,包括#import cocoa的。实现文件中,即类的实现代码中可以使用obj-c的东西,可以import,只是后缀是mm。?如果模块以函数实现,那么头文件要按 c的格式声明函数,实现文件中,c 函数内部可以用obj-c,但后缀还是mm或m。

  总结:只要cpp文件和cppinclude的文件中不包含obj-c的东西就可以用了,cpp混用obj-c的关键是使用接口,而不能直接使用实现代码,实际上cpp混用的是 obj-c编译后的o文件,这个东西其实是无差别的,所以可以用。obj-c的编译器支持cpp.

  25.目标-动作机制

  目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参 见"插座变量"部分)的形式保有其动作消息的目标。

  动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。

  程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。