半路出家的Objective C开发者,由于缺少系统性的学习,经常遇到很多困惑的问题,比如NSString类,在创建和初始化对象的时候往往不知道是用stringWithString或是initWithString,一个是静态的对象分配和初始化函数,一个又需要先alloc一下:
[NSString stringWithString:@""]
[[NSString alloc] initWithString:@""]
这2种类型的参数完全相同,只是一个多了alloc。那么问题出来了:什么时候用第一种,什么时候用第2种,貌似第一种代码量要少一点。
查阅了cocoa 设计模式之后,发现apple这样设计是由原因的。 apple 将对象的创建和初始化分开为2个阶段,先alloc分配内存,在init初始化内存,这样m种分配函数和n种初始化函数就会有m*n种组合,而在c++/c#中则必须要写m*n个构造函数,而objective c中就只有m+n个函数,这样就非常灵活。
书上就是这样说的,但是我们常见的alloc只有1个,就是alloc自己,很少看到allocWithXXX的分配函数,就是说m的值是1,这样跟c++/c#本质上就是一样的了,因此会觉得[[xxx alloc] init]会很繁琐! 实际上在计算机的早期,由于内存太少,内存管理没有那么强大,很多时候需要程序员管理,当时有一个allocWithZone函数,控制对象被分配在内存的哪个区域,程序员可以控制相关的对象分配在1个zone,这样就不会出现A对象在物理内存,而相关的B对象在Page文件中的情况。 alloc 内部实际上是调用allocWithZone来实现的。 到了现在,内存已经不是什么问题了,因此allocWithZone很少直接使用了,没有必要了,因此一般都用alloc函数。
历史就是这样发展的。
那什么时候使用stringWithString这样的静态函数?什么时候组合使用alloc和init呢?要从stringWithString的实现来分析,大概是这样实现的:
NSString* ret=[[[NSString alloc] initWithString:@"xxx"] autorelease];
return ret;
其实它内部也是先alloc再init的,只是多调用了autorelease这个函数,跟我们自己写的差不多。
autorelease涉及到内存管理方面的问题,先不多说。
直接给出结论:stringWithString适合临时变量,在一个函数体内部使用,你不用调用release函数,不太适合return到函数体外面,否则要[retain]一下,否则有时候你会发现这个对象变成nil了。
而alloc和init组合则适合在函数之间传递参数,用完之后需要手工release.
当打开垃圾收集的功能后,2种方法就差不多了。
[NSString stringWithString:@""]
[[NSString alloc] initWithString:@""]
这2种类型的参数完全相同,只是一个多了alloc。那么问题出来了:什么时候用第一种,什么时候用第2种,貌似第一种代码量要少一点。
查阅了cocoa 设计模式之后,发现apple这样设计是由原因的。 apple 将对象的创建和初始化分开为2个阶段,先alloc分配内存,在init初始化内存,这样m种分配函数和n种初始化函数就会有m*n种组合,而在c++/c#中则必须要写m*n个构造函数,而objective c中就只有m+n个函数,这样就非常灵活。
书上就是这样说的,但是我们常见的alloc只有1个,就是alloc自己,很少看到allocWithXXX的分配函数,就是说m的值是1,这样跟c++/c#本质上就是一样的了,因此会觉得[[xxx alloc] init]会很繁琐! 实际上在计算机的早期,由于内存太少,内存管理没有那么强大,很多时候需要程序员管理,当时有一个allocWithZone函数,控制对象被分配在内存的哪个区域,程序员可以控制相关的对象分配在1个zone,这样就不会出现A对象在物理内存,而相关的B对象在Page文件中的情况。 alloc 内部实际上是调用allocWithZone来实现的。 到了现在,内存已经不是什么问题了,因此allocWithZone很少直接使用了,没有必要了,因此一般都用alloc函数。
历史就是这样发展的。
那什么时候使用stringWithString这样的静态函数?什么时候组合使用alloc和init呢?要从stringWithString的实现来分析,大概是这样实现的:
NSString* ret=[[[NSString alloc] initWithString:@"xxx"] autorelease];
return ret;
其实它内部也是先alloc再init的,只是多调用了autorelease这个函数,跟我们自己写的差不多。
autorelease涉及到内存管理方面的问题,先不多说。
直接给出结论:stringWithString适合临时变量,在一个函数体内部使用,你不用调用release函数,不太适合return到函数体外面,否则要[retain]一下,否则有时候你会发现这个对象变成nil了。
而alloc和init组合则适合在函数之间传递参数,用完之后需要手工release.
当打开垃圾收集的功能后,2种方法就差不多了。