内存分配与初始化:
内存分配与初始化是分开的
Foo * foo=[[foo alloc]init]; // 内存开辟
初始化(构造函数):
1️⃣名字以init开头
2️⃣返回一个对象 (函数链)
3️⃣先执行父类的初始化方法(先初始化继承自父类的成员)
4️⃣需要检查父类初始化的返回值
5️⃣正确处理初始化中的错误(参数的判断)
id // 任意类型的对象
-(instancetype)initWtihPoint:(circle123*)_orgin andRadious:(int)_radious{
// case1:父类初始化之前,对形参有效处理
if (_radious<=0) {
_radious=1;
}
if (_orgin==nil) {
[self release];
return nil;
}
// case2:父类初始化时,对父类初始化的检测
if (!(self=[super init])) {
[self release];
return nil;
}
// case3:父类初始化之后,对当前类特有的实例变量初始化(内存分配)
if (orgin) {
[orgin release];
}
orgin=[[circle123 alloc]init];
if (!orgin) {
// 如果内存分配失败(内存不足)
[self release];
}
[orgin setX:_orgin.x];
[orgin setY:_orgin.y];
radious=_radious;
return self;
}
dealloc方法(析构函数):
注意:需要在方法中调用父类的dealloc方法
-(void)dealloc{
if (p1!=nil) {
[p1 release];
}
p1=nil;
[super dealloc];
NSLog(@"dealloc called!");
}
点语法
1、当属性中的retain换为assign时,c1.p=p1,会造成浅拷贝(c1.p与p1指向同一个地址),当p1 release 之后,c1.p为野指针
2、当属性中的retain换为copy时,c1.p=p1,会造成深拷贝(c1.p与p1指向不同的地址),各自的引用计数分别为1,所以程序没有任何问题。
init中p=[[point alloc]init]主函数中 c1.p=[p1 copy];
1、assign 在主函数中copy过了,创建的不同的地址,内存泄漏
2、retain 在主函数中copy过了,创建的不同的地址,属性用retain,释放原来的空间引用计数+1,在调用析构函数的时候,内存泄漏
3、copy 内存泄漏
init函数中 p=_p,主函数中 c1.p=p1;
1、assign 野指针,多次删除
2、retain 当创建c1对象的时候,c1.p指向p1,c1.p=p1,指向同一块空间,多次删除
3、copy 拷贝刚刚删除的空间,造成程序错误
init函数中 p=_p,主函数中 c1.p=[p1 copy];
1、assign 野指针,多次删除
2、retain p1多次删除,2️⃣pc内存泄漏
3、copy 内存泄漏(pc)2️⃣2次删除p1