递归和迭代的区别 内存管理 引用js 迭代 对象属性 属性 3

OC_内存管理(二)对象复制、循环引用问题、自动释放池-爱编程
OC_内存管理(二)对象复制、循环引用问题、自动释放池
循环调用:
1.循环引用的问题
两个对象A、B,有可能会出现特殊情况:A中包含B的实例变量;B中也包含A的实例变量,如果这两个实例变量都是强引用(A有着B的实例变量所有权,B也有A的实例变量所有权),然后在两个对象销毁时,会出现A、B都不能正常销毁的情况。下面用代码来演示循环调用问题:
ClassA的头文件Class.h代码
#import&&Foundation/Foundation.h&
//类的前向声明
@class&ClassB;
//类的前向声明与包含头文件的区别?Q:
@interface&ClassA :&NSObject
//retain在ARC下面可以使用,但是最后使用strong
@property(nonatomic,retain)ClassB&*b;
ClassA的实现文件Class.m代码
#import&"ClassA.h"
#import&"ClassB.h"
@implementation&ClassA
-(void)dealloc
&&&&NSLog(@"A的dealloc");
&&&&[_b&release];
&&&&[super&dealloc];
ClassB的头文件ClassB.h代码:
#import&&Foundation/Foundation.h&
@class&ClassA;
@interface&ClassB :&NSObject
@property(nonatomic,retain)ClassA&*a;
ClassB的实现文件ClassB.m代码:
#import&"ClassB.h"
#import&"ClassA.h"
@implementation&ClassB
-(void)dealloc
&&&&NSLog(@"B的dealloc");
& & [_a release];
&&&&[super&dealloc];
接下来就是测试文件main.m代码:
#import&&Foundation/Foundation.h&
#import&"ClassA.h"
#import&"ClassB.h"
int&main(int&argc,&const&char&* argv[]) {
&&&&@autoreleasepool&{
&&&&&&&&ClassA&*a = [[ClassA&alloc]init];
&&&&&&&&ClassB&*b = [[ClassB&alloc]init];
&&&&&&&&[a&setB:b];
&&&&&&&&[b&setA:a];
&&&&&&&&//获得所有权的是强引用
&&&&&&&&/*因为对象a,对象b都是强引用,造成循环引用,无法正常释放。
&&&&&&&&&解决方法:将其中一个改为弱引用。不获取对象所有权
&&&&&&&&&*/
&&&&&&&&[a&release];
&&&&&&&&[b&release];
&&&&return&0;
  细心地同学会发现,在ClassA和ClassB的头文件中@property的属性这是均为retain,这表明都是强引用会获得对象所有权,这样就会使程序循环调用,而无法正常释放,解决方法为将二者之一的属性改为弱引用,比如改为assign。这样就无法获得对象所有权,从而能顺利解决循环调用问题。
2.前向引用和#import包含的区别?
  一是import这两个被引用类的头文件,另一个是使用@class申明是类名,二者的区别:
  1). import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你;
  2). 在头文件中,一般只需要知道被引用的类的名称就可以了,不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称,而在类的实现部分,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
  3). 在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次被引用的,如A&&B, B&&C, C&&D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而是用@class则不会。
  4). 如果有循环依赖关系,如:A&&B, B&&A这样的相互依赖关系,如果使用#import来相互包含,那么就会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。
  所以,一般来说,@class是放在interface中的,只是为了在interface中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的实现类中,如果需要引用这个类的实体变量或者方法之类的,还是需要import在@class中声明的类进来.
对象复制:
  1.创建一个新对象,新对象的内容和旧对象的内容是一样的。
  2.给现有的对象发送copy消息,就可以复制出新的对象。
  3.类中的对象类型实例变量,如果不想受外界影响,应该采用copy的方式复制出新的对象。
对象复制分为浅复制和深复制:
  浅复制:复制对象时,如果对象中包含对象类型的实例变量,只复制指针值,新对象中的对象类型实例变量和旧对象中的对象类型实例变量指的是同一个对象。
  深复制:复制对象时,如果对象中包含对象类型的实例变量,要对对象类型的实例变量也要做对象复制,新对象中的对象类型实例变量和旧对象中的对象类型实例变量指的是不同的对象。
  复制对象有两种copy和mutableCopy:
  1.copy用于不可变对象的复制;
  2.mutableCopy复制出来的是可变对象;
自动释放池使用的五种方式
@autoreleasepool{
Book *book = [Book alloc]initWithTitle:@&Object-C& andAuthor:@&Jobs& andPrice:23.90];
[book print];
NSAutoreleasePool *pool = [NSAutoreleasePool new];
Book *book = [Book alloc]initWithTitle:@&Object-C& andAuthor:@&Jobs& andPrice:23.90];
[book print];
[pool drain]; //等效于[pool release];
@autoreleasepool&
  Book *book = [Book alloc]initWithTitle:@&Object-C& andAuthor:@&Jobs& andPrice:23.90];
  [book print];
  @autoreleasepool
    Book *book = [Book alloc]initWithTitle:@&Object-C& andAuthor:@&Jobs& andPrice:23.90];
    [book print];
@autoreleaspool
  for(int i = 0;i & 10000;i++)
    @autoreleasepool
      Book *book = [Book bookWithTitle:[NSString stringWithFormat:@&book%d&,i+1] andAuthor:[NSString stringWithFormat:@&author%d&,i+1] andPrice:20+i];
      [book print];
@autoreleasepool
  NSMutableString *str = [NSMutableString stringWithString:@&hello world&];
  NSLog(@&%@&,str);
  /*凡是不通过new、alloc、copy创建的对象都不拥有对象所有权,这种创建的对象会自动加入自动释放池,由自动释放池进行延迟释放*/
  下面对自动释放池的使用进行了总结:
  1.在自动释放池结束时会给每个管理的对象发送一次release消息
  2.[book release]的作用是将对象加入自动释放池
  3.在OC的内置类(NSString、NSArray等)中提供的类方法创建的对象实例都是(延迟释放对象),也就是在对象创建完成后将对象加入自动释放池,这种对象不需要我们去发release消息释放。(方法五)
  4.自动释放池是可以嵌套使用的,对象在加入自动释放池时,选择离它最近的释放池,就近原则,(好聪明啊!都知道懒省事),目的是为了让延迟释放的对象,尽快得到释放,降低程序期间内存的占用。(方式3)
  5.当程序中出现大量创建延迟释放对象的代码时,最好给它加一个独立的自动释放池,保证这些对象在不使用时立刻释放掉(方法四)
&摘录部分(深复制和浅复制)
3.深复制和浅复制
浅 复&制:在复制操作时,对于被复制的对象的每一层复制都是指针复制。
深 复&制:在复制操作时,对于被复制的对象至少有一层复制是对象复制。
完全复制:在复制操作时,对于被复制的对象的每一层复制都是对象复制。
1、在复制操作时,对于对象有n层是对象复制,我们可称作n级深复制,此处n应大于等于1。
2、对于完全复制如何实现(目前通用的办法是:迭代法和归档),这里后续是否添加视情况而定,暂时不做讲解。
3、指针复制俗称指针拷贝,对象复制也俗称内容拷贝。
4、一般来讲,
浅层复制:复制引用对象的指针。
深层复制:复制引用对象内容。
这种定义在多层复制的时候,就显得模糊。所以本文定义与它并不矛盾。反而是对它的进一步理解和说明。 & & & & &&
retain:始终是浅复制。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。
copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制,引用计数每次加一。始终返回一个不可变对象。
mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。
不可变对象:值发生改变,其内存首地址随之改变。
可变对象:无论值是否改变,其内存首地址都不随之改变。
引用计数:为了让使用者清楚的知道,该对象有多少个拥有者(即有多少个指针指向同一内存地址)。
版权所有 爱编程 (C) Copyright 2012. . All Rights Reserved.
闽ICP备号-3
微信扫一扫关注爱编程,每天为您推送一篇经典技术文章。递归与迭代的区别_百度知道
递归与迭代的区别
  1、“递归”是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现像.。在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知。  2、“迭代”的含义是:重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
其他类似问题
为您推荐:
提问者采纳
/}而递归是重复一组指令.) &#47,递归就是自己调用自己.;)
/ .;递归终止条件{ return abc(,如:int abc(,如.; ..:for(;c = a.){if(.; }return 0.);b = a,不断地根据变量的旧值推出新值;/迭代终止条件{a = b + c简单来说
提问者评价
按照你说的,真的成功了,好开心,谢谢你!
您可能关注的推广
迭代的相关知识
下载知道APP
随时随地咨询
出门在外也不愁 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
递归和迭代的区别
下载积分:100
内容提示:递归和迭代的区别
文档格式:DOC|
浏览次数:161|
上传日期: 23:54:14|
文档星级:
该用户还上传了这些文档
递归和迭代的区别
官方公共微信

我要回帖

更多关于 dns递归和迭代的区别 的文章

 

随机推荐