您好,欢迎访问三七文档
IOS笔试题1.Object-C有多继承吗?没有的话用什么代替?Cocoa中所有的类都是NSObject的子类,多继承在这里是用protocol委托代理来实现的,你不用去考虑繁琐的多继承,虚基类的概念,多态性在Objective-C中通过委托来实现。2.Object-C有私有方法吗?私有变量呢?Objective-C类里面的方法只有两种,静态方法和实例方法,这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西。如果没有了私有方法的话,对于一些小范围的代码重用就不那么顺手可,在里面声明一个私有方法@interfaceController:NSObject{NSString*something};+(void)thisIsAStaticMethod;-(void)thisIsAnInstanceMethod;@end@interfaceController(private)-(void)thisIsAPrivateMethod;@end@private可以用来修饰私有变量在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的3.关键字volatile有什么含义?并给出三个不同例子?一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:•并行设备的硬件寄存器(如:状态寄存器)•一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)•多线程应用中被几个任务共享的变量•一个参数既可以是const还可以是volatile吗?解释为什么。•一个指针可以是volatile吗?解释为什么。下面是答案:•是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。•是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。4.#import和#include的区别,@class代表什么?@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import而#import比起#include的好处就是不会引起重复包含5.线程和进程的区别?进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。6.堆和栈的区别?管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memoryleak。申请大小:栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。7.请介绍一下Object-C的内存管理方式1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.2.当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.3.如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.8.内存管理autorelease、retain、copy、assign的set方法和含义?你初始化(alloc/init)的对象,你需要释放(release)它。例如:NSMutableArrayaArray=[[NSArrayalloc]init];后,需要[aArrayrelease];你retain或copy的,你需要释放它。例如:[aArrayretain]后,需要[aArrayrelease];被传递(assign)的对象,你需要斟酌的retain和release。例如:obj2=[[obj1someMethod]autorelease];对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时:你或希望将对象2进行retain,以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。关于索引计数(ReferenceCounting)的问题retain值=索引计数(ReferenceCounting)NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载(dealloc)的时候,所有数组中的对象会被执行一次释放(retain值减一)。不仅仅是NSArray,任何收集类(CollectionClasses)都执行类似操作。例如NSDictionary,甚至UINavigationController。Alloc/init建立的对象,索引计数为1。无需将其再次retain。[NSArrayarray]和[NSDatedate]等“方法”建立一个索引计数为1的对象,但是也是一个自动释放对象。所以是本地临时对象,那么无所谓了。如果是打算在全Class中使用的变量(iVar),则必须retain它。缺省的类方法返回值都被执行了“自动释放”方法。(*如上中的NSArray)在类中的卸载方法“dealloc”中,release所有未被平衡的NS对象。(*所有未被autorelease,而retain值为1的)9.readwrite,readonly,assign,retain,copy,nonatomic属性的作用, 定义属性时,什么情况使用copy、assign、retain?@property是一个属性访问声明,扩号内支持以下几个属性:getter=getterName,setter=setterName,设置setter与getter的方法名readwrite,readonly,设置可供访问级别assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序(CC上有相关资料)copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的...)。assign用于简单数据类型,如NSInteger,double,bool,retain和copy用于对象,copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy的方式,a和b各自有自己的内存,就可以解决这个问题。retain会使计数器加一,也可以解决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:if(property!=newValue){[propertyrelease];property=[newValueretain];}10.对象是什么时候被释放的?引用计数为0时。autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autoreleasepool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop,系统会隐式创建一个Autoreleasepool,这样所有的releasepool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autoreleasepool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。那什么是一个Runloop呢?一个UI事件,Timercall,delegatecall,都会是一个新的Runloop11.iOS有没有垃圾回收?Objective-C2.0也是有垃圾回收机制的,但是只能在MacOSXLeopard10.5以上的版本使用。12.为什么很多内置的类,如TableViewController的delegate的属性是assign 不是retain?循环引用所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:•对象a创建并引用到了对象b.•对象b创建并引用到了对象c.•对象c创建并引用到了对象b.这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。这种情况,必须打断循环引用,通过其他规则来维护引用关系。比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。13.tableView的重用机制?查看UITableView头文件,会找到NSMutableArray*visiableCells,和NSMutableD
本文标题:62IOS笔试题
链接地址:https://www.777doc.com/doc-5065210 .html