说说你对 OC 中 load 方法和 initialize 方法的异同。——主要说一下执行时间,各自用途,没实现子类的方法会不会调用父类的?
说说你对 block 的理解。—— 三种 block,栈上的自动复制到堆上,block 的属性修饰符是 copy,循环引用的原理和解决方案。
说说你对 runtime 的理解。——主要是方法调用时如何查找缓存,如何找到方法,找不到方法时怎么转发,对象的内存布局。
提高方法查找机制效率-Class Cache
通过上文我们知道,在OC中,方法是通过isa指针,查找Class中的Method list来查询的。而一个类往往会实现很多方法,每次调用都查询一次Method list的分发表(dispatch table)的代价是很高的(因为,这种查询可能每个RunLoop就执行上亿次)。这也就引入了Class Cache.
Class Cache认为,当一个方法被调用,那么它之后被调用的可能性比较大。
举个例子,我们常见的alloc,init,调用顺序如下
CustomObject * obj = [[CustomObject alloc] init];
alloc是类方法,沿着isa找到CustomObject类元对象,发现没有实现alloc
沿着super,找到NSObject类元方法,执行alloc方法,并把alloc加入到NSObject类元对象的Class Cache中
init是实例方法,沿着isa找到CustomObject的类对象,发现没有实现init
沿着super,找到NSObject类对象,执行init,并把init加入到NSObject的类对象Class Cache中
这里,再提一下alloc,init两个方法
alloc方法的文档
初始化isa,其他所有属性被设为0
init
NSObject的init返回self,其余的子类要调用[super init]进行必要的初始化工作。
为什么要放在一起写?
因为alloc和init有可能返回不同的对象
id a = [NSMutableArray alloc];
id b = [a init];
NSLog(@"%p",a);
NSLog(@"%p",b);
输出
0x7fc550400fb0
0x7fc5505523a0
- 方法的selector
这两个参数为方法的实现提供了调用者的信息。之所以说是隐藏的,是因为它们在定义方法的源代码中没有声明。它们是在编译期被插入实现代码的。
虽然这些参数没有显示声明,但在代码中仍然可以引用它们。我们可以使用self来引用接收者对象,使用_cmd来引用选择器。如下代码所示:
- strange
{
id target = getTheReceiver();
SEL method = getTheMethod();
if ( target == self || method == _cmd )
return nil;
return [target performSelector:method];
}
当然,这两个参数我们用得比较多的是self,_cmd在实际中用得比较少。
获取方法地址
Runtime中方法的动态绑定让我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。不过灵活性的提 升也带来了性能上的一些损耗。毕竟我们需要去查找方法的实现,而不像函数调用来得那么直接。当然,方法的缓存一定程度上解决了这一问题。
我们上面提到过,如果想要避开这种动态绑定方式,我们可以获取方法实现的地址,然后像调用函数一样来直接调用它。特别是当我们需要在一个循环内频繁地调用一个特定的方法时,通过这种方式可以提高程序的性能。
NSObject类提供了methodForSelector:方法,让我们可以获取到方法的指针,然后通过这个指针来调用实现代码。我们需要将methodForSelector:返回的指针转换为合适的函数类型,函数参数和返回值都需要匹配上。
我们通过以下代码来看看methodForSelector:的使用:
void (*setter)(id, SEL, BOOL);
int i;
setter = (void (*)(id, SEL, BOOL))[target
methodForSelector:@selector(setFilled:)];
for ( i = 0 ; i < 1000 ; i++ )
setter(targetList[i], @selector(setFilled:), YES);
这里需要注意的就是函数指针的前两个参数必须是id和SEL。
当然这种方式只适合于在类似于for循环这种情况下频繁调用同一方法,以提高性能的情况。另外,methodForSelector:是由Cocoa运行时提供的;它不是Objective-C语言的特性。
消息转发
当一个对象能接收一个消息时,就会走正常的方法调用流程。但如果一个对象无法接收指定消息时,又会发生什么事呢?默认情况下,如果是以 [object message]的方式调用方法,如果object无法响应message消息时,编译器会报错。但如果是以perform…的形式来调用,则需要等到运 行时才能确定object是否能接收message消息。如果不能,则程序崩溃。
通常,当我们不能确定一个对象是否能接收某个消息时,会先调用respondsToSelector:来判断一下。如下代码所示:
if ([self respondsToSelector:@selector(method)]) {
[self performSelector:@selector(method)];
}
不过,我们这边想讨论下不使用respondsToSelector:判断的情况。这才是我们这一节的重点。
当一个对象无法接收某一消息时,就会启动所谓”消息转发(message forwarding)“机制,通过这一机制,我们可以告诉对象如何处理未知的消息。默认情况下,对象接收到未知的消息,会导致程序崩溃,通过控制台,我们可以看到以下异常信息:
-[SUTRuntimeMethod method]: unrecognized selector sent to instance 0x100111940
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SUTRuntimeMethod method]: unrecognized selector sent to instance 0x100111940'
这段异常信息实际上是由NSObject的”doesNotRecognizeSelector”方法抛出的。不过,我们可以采取一些措施,让我们的程序执行特定的逻辑,而避免程序的崩溃。
消息转发机制基本上分为三个步骤:
- 动态方法解析
- 备用接收者
- 完整转发
下面我们详细讨论一下这三个步骤。
动态方法解析
对象在接收到未知的消息时,首先会调用所属类的类方法+resolveInstanceMethod:(实例方法)或 者+resolveClassMethod:(类方法)。在这个方法中,我们有机会为该未知消息新增一个”处理方法”“。不过使用该方法的前提是我们已经 实现了该”处理方法”,只需要在运行时通过class_addMethod函数动态添加到类里面就可以了。如下代码所示:
void functionForMethod1(id self, SEL _cmd) {
NSLog(@"%@, %p", self, _cmd);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSString *selectorString = NSStringFromSelector(sel);
if ([selectorString isEqualToString:@"method1"]) {
class_addMethod(self.class, @selector(method1), (IMP)functionForMethod1, "@:");
}
return [super resolveInstanceMethod:sel];
}
不过这种方案更多的是为了实现@dynamic属性。
备用接收者
如果在上一步无法处理消息,则Runtime会继续调以下方法:
- (id)forwardingTargetForSelector:(SEL)aSelector
如果一个对象实现了这个方法,并返回一个非nil的结果,则这个对象会作为消息的新接收者,且消息会被分发到这个对象。当然这个对象不能是self自身,否则就是出现无限循环。当然,如果我们没有指定相应的对象来处理aSelector,则应该调用父类的实现来返回结果。
使用这个方法通常是在对象内部,可能还有一系列其它对象能处理该消息,我们便可借这些对象来处理消息并返回,这样在对象外部看来,还是由该对象亲自处理了这一消息。如下代码所示:
@interface SUTRuntimeMethodHelper : NSObject
- (void)method2;
@end
@implementation SUTRuntimeMethodHelper
- (void)method2 {
NSLog(@"%@, %p", self, _cmd);
}
@end
#pragma mark -
@interface SUTRuntimeMethod () {
SUTRuntimeMethodHelper *_helper;
}
@end
@implementation SUTRuntimeMethod
+ (instancetype)object {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (self != nil) {
_helper = [[SUTRuntimeMethodHelper alloc] init];
}
return self;
}
- (void)test {
[self performSelector:@selector(method2)];
}
- (id)forwardingTargetForSelector:(SEL)aSelector {
NSLog(@"forwardingTargetForSelector");
NSString *selectorString = NSStringFromSelector(aSelector);
// 将消息转发给_helper来处理
if ([selectorString isEqualToString:@"method2"]) {
return _helper;
}
return [super forwardingTargetForSelector:aSelector];
}
@end
这一步合适于我们只想将消息转发到另一个能处理该消息的对象上。但这一步无法对消息进行处理,如操作消息的参数和返回值。
完整消息转发
如果在上一步还不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。此时会调用以下方法:
- (void)forwardInvocation:(NSInvocation *)anInvocation
运行时系统会在这一步给消息接收者最后一次机会将消息转发给其它对象。对象会创建一个表示消息的NSInvocation对象,把与尚未处理的消息 有关的全部细节都封装在anInvocation中,包括selector,目标(target)和参数。我们可以在forwardInvocation 方法中选择将消息转发给其它对象。
//内存布局
http://blog.csdn.net/cx_wzp/article/details/50905708
说说你对 MVC 和 MVVM 的理解。—— MVC 的 C 太臃肿,可以和 V 合并,变成 MVVM 中的 V,而 VM 用来将 M 转化成 V 能用的数据。
说说 UITableView 的调优。——一方面是通过 instruments 检查影响性能的地方,另一方面是估算高度并在 runloop 空闲时缓存。
谈谈你对 ARC 的理解。ARC 是编译器完成的,依靠引用计数,谈谈几个属性修饰符的内存管理策略,什么情况下会内存泄露
7、层和UIView的区别是什么?
答:两者最大的区别是,图层不会直接渲染到屏幕上,UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器。一个UIView上可以有n个CALayer,每个layer显示一种东西,增强UIView的展现能力。
3、垃圾回收和引用计数的区别?引用计数为0了才释放
2、自动释放池的作用?
autorelease的使用
自动释放池:是用来自动释放对象的,不需要关心对象释放的时间,不需要关心对象什么时候调用release
自动释放池释放的时间:自动释放池结束
自动释放池原理:当池子结束,会想池子里面的对象发送一条release消息
自动释放池使用:1.创建对象 2.加入自动释放池
两种使用方式:
①Person *p = [Person new];
[p autorelease];
②Person *p1 = [[Person new]autorelease];
注意事项:
1.并不是放到自动释放池中的代码中,就会自动加入到自动释放池的
需要我们调用autorelease方法的
在自动释放池的外部调用autorelease方法,是不会被加入到自动释放池中的
不管这个对象是在自动释放池内部还是外部创建的,只要在这个对象在自动释放池中调用autorelease方法,那么就会被放到自动释放池中
总结:不管是在什么地方创建的对象,都必须在自动释放池中,调用autorelease方法,才会被加入自动释放池中
2.自动释放池的嵌套使用:自动释放池是个栈结构,先进后出(每个自动释放池就当成一个桶,先放到下面的,最后拿出来,有利于理解)
延迟调用release,在自动释放池结束时,让对象调用release
注意:自动释放池可不是直接释放对象,而只是让对象release一次,如果对象的retainCount为2,那么自动释放池只能让retainCount变为1,对象就销毁不了
3.自动释放池中不适合放占用内存比较大的对象
1)这是种延迟释放机制,是直到自动释放池结束才释放的,中间大内存文件一直在占用内存
2)不要把大量循环操作放到同一个@autoreleasepool(自动释放池)之间,这样会造成内存峰值的
4.错误用法:
1)连续调用多次autorelease,释放池结束时会执行两次release
⁃ 注意:一个retainCount为1的对象,如果release两次,程序是会崩溃的
· 2)alloc之后调用了autorelease,之后又调用了release(还是release两次)
5.autorelease的应用场景:
经常用来在类方法中,快速创建一个对象
我们平常定义一个指针,先alloc,再init,最后还要手动释放,太麻烦,索性直接当定义出来的同时,调用一下autorelease方法,当自动释放池结束的时候,自动就release,通常可以用于重写init的时候,直接放在init里
【小结】:
1:自动释放池的数据结构
自动释放池是以栈的形式实现,当你创建一个新的自动释放池,它将会被添加到栈顶。接受autorelease
消息的对象将会呗放入栈顶
2:如何持有对象
当我们使用alloc,copy,retain对象获取一个对象时,我们需要负责显示的安排对象的销毁,其他方法获取的
的对象将交给自动释放池进行释放(单例模式除外)
3:release和drain的区别
当我们向自动释放池pool发送release消息,将会向池中临时对象发送一条release消息,并且自身也会呗销毁。
向它发送drain消息时,只会指定前者。
1.Objective-C可以实现多继承吗?可以实现多个接口吗?Category是什么?重写一个类的方式是用继承好还是用分类好?为什么?
2.OC使用协议实现多继承,可以遵守多个协议实现多接口。category是OC中的类别,类别是用于给一个现有类添加新方法。重写类一般采用继承的方式,分类(类别)在给以个类添加同名方法后,会造成原有类中方法的实效,而继承重写的方法,依然可以在使用父类对象调用该方法。
3.定义属性的时候,什么时候使用retain/copy/assign?写一个setter方法,用于完成@property(nonatomic,retain) NSString* name;写一个setter方法,用于完成@property(nonatomic,copy)NSString* name;
retain用于保留对象的引用计数,在使用retain声明的属性做赋值的时候,成员变量指针会保留被赋值对象的引用计数。
copy声明的属性,在使用属性赋值的时候会,成员指针会指向新副本,这个副本是一个不可变副本,不论赋值对象是不是可变的。
assign用于基本数据类型的属性声明,不涉及到内存管理的问题,也是缺省参数
retain声明的属性的setter方法展开
- (void)setName:(NSString*)name
{
if(_name != name)
{
[_namerelease];
_name= [name retain];
}
}
copy声明的属性的setter方法展开
- (void)setName:(NSString*)name
{
if(_name != name)
{
[_namerelease];
_name= [name copy];
}
}
4.什么时候使用NSMutableArray/什么时候使用NSArray
NSMutableArray一般在需要随时更改数组结构的时候使用
NSArray一般用于保存一些不需要修改逻辑的数据
5.实现字符串“I LOVE CHINA”反串成“CHINA LOVE I”
- pch文件的作用
.pch表示"precompiled header",这是一个你工程要用到的来自于外部框架的头文件列表。xcode将编译这些头到文件,这将减少你在选择Build或Build and Go时编译项目的时间。通常用到的头文件已经自动包含了pch,系统编译每个cpp文件前,都会先include这个文件。这样就节省了添加include的时间,相当于加速编译
还有就是可以再这里面放入宏,在整个工程中都可以用
7.怎样解决重复编译
ifndef _DEBUG
ifdef USE_MYLIB
................
endif
- awakeFromNib与viewDidLoad区别
awakeFromNib
当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象是执行awakeFromNib。
viewDidLoad
当view对象被加载到内存是就会执行viewDidLoad,所以不管通过nib文件还是代码的方式创建对象都会执行viewDidLoad。 - LayoutSubviews何时会被调用
当要调整subViews时候,需要重写layoutSubviews方法。
1:初始化init方法时候不会触发。
2:滚动UIScrollView时会触发
3:旋转UIScreen时会触发
4:当改变view的值时候会触发,前提是frame前后值发生了变化
5:当改变UIview的大小时候会触发 - public/private/protected的具体区别
public公共,加上这个修饰的类或属性,可以在同一个包或者别的包里面访问
private私有的,加上这个修饰的类或属性,只能在同类里访问,同包和别的包不能访问
protected保护,加上这个修饰的类或属性,只能在类和同包访问,别的包不能访问 - ARC是什么
ARC是iOS 5推出的新功能,全称叫ARC(Automatic Reference Counting)。简单地说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。
该机能在iOS 5/ Mac OS X 10.7开始导入,利用Xcode4.2可以使用该机能。简单地理解ARC,就是通过指定的语法,让编译器(LLVM
3.0)在编译代码时,自动生成实例的引用计数管理部分代码。有一点,ARC并不是GC,它只是一种代码静态分析(Static
Analyzer)工具。
12.写一个“标准”宏,这个宏输入两个参数并返回较小的
define MIN(X,Y)((X)>(Y)?(Y):(X))
13.Objective-c中有多重继承么?不是的话有声明替代方式?
没有多继承,可以通过协议模拟多继承
14.Objective-c中有私有方法吗?私有变量呢?
没有私有方法,但可以将方法直接实现在.m文件中不在.h文件中声明时,外部也不能访问。
有私有变量
15.iPhone OS中有没有垃圾回收?
没有
16.常见的object-c的数据类型有哪些,和c的基本类型有什么区别
答:常见的object-c的数据类型有NSInteger、CGFloat、NSString、NSNumber、NSArray、NSData,NSInteger会根据系统是32位还是64位来决定是本身是int还是Long,
CGFloat会根据系统是32位还是64位来决定是本身是float还是double,NSString、NSNumber、NSArray、NSData都是指针类型的对象,在堆中分配空间,而c语言中的char,[]等都是在栈中分配空间
17.id声明的对象有什么特性?
id声明的对象具有运行时的特性,即可以指向任意类型的objcetive-c的对象;
18.想nil对象发送消息会发生什么?
答:在Objective-C中向nil发送消息是完全有效的,只是在运行时不会有任何作用。
19.什么是block?block实现原理?
答:block是一个特殊的OC对象,它建立在栈上,而不是堆上,这么做一个是为性能考虑,还有就是方便访问局部变量。默认情况下block使用到的局部变量都会被复制,而不是保留。所以它无法改变局部变量的值。如果在变量面前加上__block,那么编译器回去不会复制变量,而是去找变量的地址,通过地址来访问变量,实际上就是直接操作变量。另外block是在栈上分配的,所以一旦离开作用域,就会释放,因此如果你要把快用在别的地方,必须要复制一份。block是不能保留的,
retain对块没有意义。
20.C++和OC,JAVA和OC之间的区别?
C++是功能强大,丰富的面向对象编程语言,具有私有、公有、保护权限的三种成员变量和成员方法,具有私有、公有、保护三种继承方式,具有重写,重载,虚函数,虚基类等多态方式,通过虚基类实现代理回调。自定义类可以没有父类。另外具备向量,模板,友元,重载运算符等多种独特语法
Obj-C是针对mac OS和iOS设备应用程序开发的专属编程语言,采用动态继承,消息方法机制,没有真正的重写机制,没有私有方法,继承方式为公有,具备协议,类别,Block等独有的语法,万用父类为NSObject
JAVA是老牌的面向对象语言,编写的程序在JAVA虚拟机上运行,真正实现了一次编译到处运行,具有复杂的内存回收机制,单继承模式,接口语法类似Obj-C的协议
21.抽象与接口的区别?
声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。
接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static
final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof运算符可以用来决定某对象的类是否实现了接口。
22.nil与NULL的区别?
从Objective-C语言的官方说法上看,nil表示指向对象的指针即所谓对象的引用为空,NULL表示指向基础类型变量即C语言变量的指针为空。如果在非ARC程序的编写过程中,两个空是可以互换的,但是在ARC环境下,普通指针和对象引用被严格限制,不能交换使用,因此也应尽量不互换使用nil与NULL
- BOOL与bool的区别?
bool是C语言C99标准中增添的变量类型,Object-C仅仅是从C语言继承了这种类型,该类型有true和false两个值,表示真和假。BOOL是Obj-C独有的布尔类型,有YES和NO两个值,分别是1和0的宏。Obj-C中同时认为所有非0的值都是真值,0为假值
24.OC如何实现私有方法?
Obj-C语法中并没有私有方法的概念,但是由于Obj-C是通过导入其他类的头文件来获取其他类所拥有的成员方法的声明,因此可以采用编写方法时,不声明,或仅在.m文件中的匿名类别中声明的方式,使方法对外不可见,即可达到方法私有化的目的。但是外部类仍然可以通过@selector来访问确实存在的私有方法,因此严格来讲Obj-C确实不能真正实现方法私有化
25.#import和#include的区别@ class代表什么
预编译指令
Objective-C:#import
C,C++:#include
import由gcc编译器支持
在Objective-C中,#import被当成#include指令的改良版本来使用。除此之外,#import确定一个文件只能被导入一次,这使你在递归包含中不会出现问题。
使用哪一个还是由你来决定。一般来说,在导入Objective-C头文件的时候使用#import,包含C头文件时使用#include。比如:
import
include
include
import比起#include的好处就是不会引起交叉编译
二、@class是用来做类引用的
@class就是告诉编译器有这么一个类,至于类的定义是啥不知道
@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import
- NSString和NSMutableString的区别
NSString是一个不可变的字符串对象。这不是表示这个对象声明的变量的值不可变,而是表示它初始化以后,你不能改变该变量所分配的内存中的值,但你可以重新分配该变量所处的内存空间。而NSMutableString是可变的,意味着你可以追加它的内存空间,或者修改它所分配的内存空间中的值。
27..关于语句NSString * str= [NSData alloc]init,编译和运行分别str代表什么对象?
首先,声明NSString str是告诉编译器,str是一个指向某个Objective-C对象的指针。因为不管指向的是什么类型的对象,一个指针所占的内存空间都是固定的,所以这里声明成任何类型的对象,最终生成的可执行代码都是没有区别的。这里限定了NSString只不过是告诉编译器,请把str当做一个NSString来检查,如果后面调用了非NSString的方法,会产生警告。
接着,你创建了一个NSData对象,然后把这个对象所在的内存地址保存在str里。那么运行时,str指向的内存空间就是一个NSData对象。你可以把str当做一个NSData对象来用。
28.socket通信的几个关键步骤
面向连接的socket通信就像与对方打电话,首先需要通过电话建立一个连接,连接建立好之后,彼此才能双向通信。它有几个关键步骤
服务器端通常以守护进程的方式实现:
1:创建守护进程
2:获取或注册服务
3:创建socket并绑定地址
4:开始监听
5:接收客户端连接请求
6:进行数据传输
客户端
1:获取或注册服务
2:创建socket
3:发送连接请求
29.类别意义?与继承的区别
当我们添加头文件以后,对已知的类,会自动提示你对这个类添加的方法
主要用途,对于原生不会造成破坏,使用原生就可以提示出你的方法
30.Core Foundation中提供了哪几种操作Socket的方法?
CFNetwork、CFSocket和BSDSocket
31.用id声明的对象有什么特性?
Ø没有号
Ø动态数据类型
Ø可以指向任何类的对象(设置是nil),而不关心其具体类型
Ø在运行时检查其具体类型
Ø可以对其发送任何(存在的)消息
32,self.name=“object”name=“object”有什么区别?
前者实际上是调用了set方法给变量赋值而后者是直接给变量赋值
33.shell中,将command1的输出作为command2的输出应该使用的命令是?
重定向命令>
command1>command2
34.下面的数据结构中不属于线性结构的是:栈,链表,二叉树,线性表
线性结构:栈,链表,线性表
非线性结构:二叉树
35,oc中有没有多继承,如果没有用什么方法替代?
没有用协议代替多继承
36.常见的Objective-C的数据类型有哪些,和C的基本数据类型有什么区别
OC中常用数据类型有NSArray,NSDictionary,NSData,NSString,NSMutbleString等等,和C的最大区别为OC中的类型是类类型,需要实例化对象才能用。C中是一般数据类型直接操作内存空间
37.self.name=@“aa”和_name=@“aa”的区别
答:self.name=@“aa”是通过set方法进行赋值,_name=@“aa”是直接复制给成员变量
38.C语言中指针与数组的区别
答:指针是变量可以修改指向的方向,数组名是地址常量,不能被修改
39.new delete malloc free的含义
c++:new申请内存,delete释放掉指针指向的内存
c:malloc动态申请内存,free释放指针指向的内存
40.常引用什么时候使用
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就要使用常引用
41.c/oc/c++有什么区别和联系
C相对于C++和OC而言更偏重于逻辑算法,这是因为C是面向过程,C++和OC都是面向对象。C和C++的联系:C是C++的一个自洽子集,C++是C的超集,OC是C的扩展,C++和OC基本兼容C的语法。
42.const的用法
const修饰变量表示该变量是只读变量(有些人管它叫常量),即只能引用而不能修改
constint p;表示指针变量P指向的数据不能改
intconst p;表示指针变量P的值不能该,或者说是指针P的指向不能改
43.[pool release]和[pool drain]有什么区别
drain和release都会促使自动释放池对象向池内的每一个对象发送release消息来释放池内对象的引用计数,但是release触发的这个操作,不会考虑对象是否需要release,而drain会在自动释放池向池内对象发送release消息的时候,考虑对象是否需要release
44.自动释放池和GC一样吗,iphone有没有GC
在引用计数环境下,
ios是没有垃圾回收的,自动释放池是oc中管理内存的一种方式,它和gc是本质区别的,自动释放池管理内存的前提是,必须把要管理内存的对象加入池内,才会生效。而gc是不断检测当前程序中是否有不再使用的内存进而释放。
45.当A类 中的某个方法执行到某处时,这时想在B类中执行某个方法,如何做?并做简单说明
用代理执行代理方法
说明:在b类中实现协议方法,设置a的代理为b,在指定方法内调用代理的协议方法
46.类别的作用?
答案:category可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。
并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中。
(2)创建对私有方法的前向引用。
(3)向对象添加非正式协议。
47.简述extern
C的作用
可以在C++中使用C的已编译好的函数模块,在c++中么用到c语言写的函数,声明一下,在DLL中经常看到,避免C++
name mangling,主要用于动态链接库,使得导出函数名称与C语言规则一致(不改变),方便不同的编译器甚至是不同的开发语言调用。
extern
"C"是告诉C++编译器以C Linkage方式编译,也就是抑制C++的name
mangling机制。
编程:
1.写出@proerty(nonatomic,retain)Person
*person;@synthesize person具体实现。
- (void)setPerson:(Person *)person
{
if(_person !=person){
[_personrelease];
[_person =person retain];
}
}
- (Person *)person {
return _person;
}
2.从普通id类型对象转换成数字对象,因为配置了限定词.1f,所以结果四舍五入,并保留一位小数
NSDictionary* rowData =[NSDictionarydictionaryWithObjectsAndKeys:@"46.95",@"price",nil];
NSLog(@"a double value:%.1f",[(NSNumber*)[rowDataobjectForKey:@"price"] doubleValue]);
输出:
a double value:47.0
3,写一个委托的interface
#import
@protocolMyDelegate;//声明
@interfaceMyClass:NSobject
{
iddelegate;
}
@end
@protocolMyDelegate//委托方法
-(void)selector:(NSString *)args;
@end
4:请看下面一段代码
staticint a=1;
intmain(){
intb=2;
char*c=NUll;
c=(char*)malloc(100*sizeof(char));
return0;
}
问:1,访问abc三者的效率从高到低依次是:
bca
2,在最坏情况下排序速度最快的是:归并排序
复杂度最高的是:快排
a,快排,冒泡,堆,归并
5.看下面的程序
=========================================
NSMutableArray *arr = [[NSMutableArrayarray] retain];
NSString *str = [NSStringstringWithFormat:@"test"];
[str retain];
[arr addObject:str];
NSLog(@"%@%lu",str,[strretainCount]);
[str retain];
[str release];
[str release];
NSLog(@"%@%lu",str,[strretainCount]);
[arr removeObject:str];
NSLog(@"%@%lu",str,[strretainCount]);
==================================================
三次打印的retainCount分别是什么,为什么?
答:
分别是3,2,1,
初始化的时候的为1,retain的时候+1,往数组里add的时候+1,release的时候-1,从数组里移除的时候-1
网友评论