对象所有权
对象所有权的持有,一般有以下几种方式:
1、初始化方法
NSString
参数
- (id)initWithName:(NSString *)name
{
self = [super init];
if (self) {
_name = [name copy]; // 设置对象所有权
}
return self;
}
- 其他参数
- (id)initWithName:(id)name
{
self = [super init];
if (self) {
_name = [name retain]; // 设置对象所有权
}
return self;
}
2、设置方法
- 直接赋值
- (void)setCPU:(CPU *)cpu
{
_cpu = cpu;
}
- 直接保留对象,在
dealloc
中释放对象
- (void)setCPU:(CPU *)cpu
{
_cpu = [cpu retain];
}
- 释放旧对象,保留新对象,在
dealloc
中释放对象
- (void)setCPU:(CPU *)cpu
{
if (_cpu != cpu) {
[cpu release];
_cpu = [cpu retain];
}
}
dealloc
定义
dealloc
方法作用是当对象的引用计数为0时,系统会自动调用dealloc
方法,回收内存,它的一般写法是:
- (void)dealloc
{
[super dealloc];
}
或
- (void)dealloc
{
[_obj release];
[super dealloc];
}
- 调用父类的
dealloc
方法,是因为子类的某些实例是继承自父类的,所以需要继承父类的dealloc
方法来释放父类拥有的这些对象。 - 调用顺序:一般当子类的对象释放完时,再释放父类的所拥有的实例。这一点与调用初始化方法的
[super init]
,正好相反。
示例
1、示例描述
- 设有一个交通工具类
Vehicle
- 创建一个小汽车
Car
类,并继承Vehicle
- 小汽车拥有引擎类
Engine
2、代码 - 创建
Vehicle.h
#import <Foundation/Foundation.h>
@interface Vehicle : NSObject
{
NSString *_name;
}
- (id)initWithName:(NSString *)name;
@end
- 创建
Vehicle.m
#import "Vehicle.h"
@implementation Vehicle
// 初始化交通工具名称name
- (id)initWithName:(NSString *)name
{
self = [super init];
if (self) {
_name = [name copy]; // 设置对象所有权
}
return self;
}
// 重写dealloc方法
- (void)dealloc
{
NSLog(@"Vehicle dealloc");
[_name release]; // 释放当前的_name
[super dealloc]; // 调用父类方法
}
@end
- 创建
Car.h
#import "Vehicle.h"
@class Engine;
@interface Car : Vehicle
{
Engine *_engine; // 创建引擎对象
}
- (void)setEngine: (Engine *)engine;
@end
- 创建
Car.m
#import "Car.h"
#import "Engine.h"
@implementation Car
// 创建设置引擎方法
- (void)setEngine: (Engine *)engine
{
if (_engine!=engine) { // 设置对象所有权,避免重复对象
[_engine release]; // 释放旧的对象所有权
_engine = [engine retain]; // 保留新的对象所有权
}
}
// 重写dealloc方法
-(void)dealloc
{
NSLog(@"Car dealloc");
[_engine release]; // 释放_engine
[super dealloc];
}
@end
- 创建
Engine.h
#import "Vehicle.h"
@interface Engine : Vehicle
@end
- 创建
Engine.m
#import "Engine.h"
@implementation Engine
@end
main
方法中调用
#import <Foundation/Foundation.h>
#import "Vehicle.h"
#import "Car.h"
#import "Engine.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *name = [NSString stringWithFormat:@"BMW"];
Car *car = [[Car alloc] initWithName: name];// name的对象所有权交给了Car类
[name release];// 释放name自己的引用计数
Engine *engine = [[Engine alloc] init];
[car setEngine:engine]; // Engine的引用计数+1,将Engine的对象所有权交给Car类,Car类负责释放
[engine release];// 释放engine自己的引用计数
NSLog(@"Car的引用计数%ld",[car retainCount]);// 引用计数为1
[car release];// 释放的时候,引用计数为0,会调用Car的dealloc方法,然后释放持有的engine对象,然后再调用父类Vehicle的dealloc方法,释放name对象
}
return 0;
}