1.内存的创建和释放
让我们以Object-c世界中最最简单的申请内存方式展开,谈谈关于一个对象的生命周期。首先创建一个对象:
id tt= [[test alloc]initWithName:@"百合不是茶" setLike:2];
对于test来说他的引用计数就增加了+1,原因就是他调用了alloc来创建了一块只属于他的内存,这样对象的引用计数 就得+1. 另外,Object-c中的另两个关键字retain和copy也会将对象的引用计数+1.根据Object-c的内存管理机制,我们在使用完 “testObject”后,需要释放它。
[test release];
3.属性关键字
@property (nonatomic, assign) int sex;
@property (nonatomic, retain) NSString* name;
可以看到关键之@property后的括号出现了四个特征性关键字:nonatomic , assign , retain , settet, 这些关键字直接告诉编译器后面的变量用何种方式
assign 赋值方式 不复制不保留,直接赋值 默认值 基本数据类型和本类不直接拥有的对象 retain +1 赋值方式 将新值保留一份赋覆盖原值 不是默认值 大部分对象可使用 copy +1 赋值方式 将新值复制一份赋覆盖原值 不是默认值 字符串选择性使用 readwrite 读写权限 生成getter和setter两个方法 默认值 变量可读取可修改 readonly 读写权限 只生成getter方法 不是默认值 变量只读不可修改 atomic 原子性 原子操作 默认值 可以保留在多线程环境下,能安全的存取值 nonatomic 原子性 非原子操作 不是默认值 不生成多线程同步内容 getter 存取方法 自定义取方法 不是默认值 setter 存取方法 自定义赋值方法 不是默认值 关于nonatomic,如果我们能确定不需要多线程访问时,强烈推荐使用这个关键字,因为atomic对于性能的损失相对较大 如果是类的delegate,推荐使用assign关键字,原因是避免了retain的死循环造成的对象无法真正的释放
下面的内容时来自网络,
3.ARC新增关键字 ARC新增两个武功高强的左右护法:strong 和 weak strong的含义和retain相同,weak和assign相同,修饰完的属性变量用法也是完全没有改变,不过strong和weak只能修饰对象。 苹果官方对于ARC机制中对象的内存引用规则: (1)任何对象,如果仍有持有者,就不会销毁 (2)任何对象,已经没有任何持有者,即自动销毁 持有者就是指向对象的指针,如果是strong修饰的,即是对象的持有者,如果是weak属性的,则不是持有者 4.ARC机制的使用规则 对于ARC机制的使用,苹果发布了几条重要的规则需要开发者遵守。单单看那些生搬硬套的东西难免生涩,根据开发经验将规则总结如下: (1)不能调用dealloc,不能重写和调用retain,release,retainCount 和autorelease,同理,@selector(retain),@selector(release)这些曲线救国的方法也不能调用。 dealloc虽然能够重写,但是不能调用[super dealloc]之类的方法,CoreFoundation框架由于非从属cocoa框架,所以CFRetain和CFRelease仍然正常使用。 (2)不能使用NSAllocateObjec或NSDeallocateObject函数来创建对象 (3)不能在C语言的结构体中使用对象指针,同时建议用object-c的类来管理数据而不是结构体 (4)不得使用NSAutoreleasePool对象。ARC中,全部使用@autorelease关键字代替,且比NSAutoreleasePool更高效 (5)不得使用内存Zone,那些牵涉NSZone的方法都不得使用。 (6)不得对一个属性变量的取值方法命名以new开头 (7)outlet均用weak关键字修饰,除非他是xib中最顶部的界面元素,则需要strong。 (8)Core Foundation不适合ARC,该创建的仍创建,该释放的仍释放。 property中的strong 、weak、copy 、assign 、retain 、unsafe_unretained 与autoreleasing区别和作用详解 iOS5中加入了新知识,就是ARC,其实我并不是很喜欢它,因为习惯了自己管理内存。但是学习还是很有必要的。 在iOS开发过程中,属性的定义往往与retain, assign, copy有关,我想大家都很熟悉了,在此我也不介绍,网上有很多相关文章。 现在我们看看iOS5中新的关键字strong, weak, unsafe_unretained. 可以与以前的关键字对应学习strong与retain类似,weak与unsafe_unretained功能差不多(有点区别,等下会介绍,这两个新 关键字与assign类似)。在iOS5中用这些新的关键字,就可以不用手动管理内存了,从java等其它语言转过来的程序员非常受用。 strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切 1 @property (nonatomic, strong) NSString *string1; 2 @property (nonatomic, strong) NSString *string2; 有这样两个属性, 1 @synthesize string1; 2 @synthesize string2; 猜一下下面代码将输出什么结果? 1 self.string1 = @"String 1"; 2 self.string2 = self.string1; 3 self.string1 = nil; 4 NSLog(@"String 2 = %@", self.string2); 结果是:String 2 = String 1 由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1", 如果你对retain熟悉的话,这理解并不难。 接着我们来看weak关键字: 如果这样声明两个属性: 1 @property (nonatomic, strong) NSString *string1; 2 @property (nonatomic, weak) NSString *string2; 并定义 1 @synthesize string1; 2 @synthesize string2; 再来猜一下,下面输出是什么? 1 self.string1 = @"String 1"; 2 self.string2 = self.string1; 3 self.string1 = nil; 4 NSLog(@"String 2 = %@", self.string2); 结果是:String 2 = null 分析一下,由于self.string1与self.string2指向同一地址,且string2没有retain内存地址,而 self.string1=nil释放了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为 nil。这样的好处能有效的防止野指针。在c/c++开发过程中,为何大牛都说指针的空间释放了后,都要将指针赋为NULL. 在这儿用weak关键字帮我们做了这一步。 接着我们来看unsafe_unretained 从名字可以看出,unretained且unsafe,由于是unretained所以与weak有点类似,但是它是unsafe的,什么是unsafe的呢,下面看实例。 如果这样声明两个属性: 并定义 1 @property (nonatomic, strong) NSString *string1; 2 @property (nonatomic, unsafe_unretained) NSString *string2; 再来猜一下,下面的代码会有什么结果? 1 self.string1 = @"String 1"; 2 self.string2 = self.string1; 3 self.string1 = nil; 4 NSLog(@"String 2 = %@", self.string2); 请注意,在此我并没有叫你猜会有什么输出,因为根本不会有输出,你的程序会crash掉。 原因是什么,其实就是野指针造成的,所以野指针是可怕的。为何会造成野指针呢?同于用unsafe_unretained声明的指针,由于 self.string1=nil已将内存释放掉了,但是string2并不知道已被释放了,所以是野指针。然后访问野指针的内存就造成crash. 所以尽量少用unsafe_unretained关键字。 strong,weak, unsafe_unretained往往都是用来声明属性的,如果想声明临时变量就得用__strong, __weak, __unsafe_unretained, __autoreleasing, 其用法与上面介绍的类似。 还是看看实例吧。 1 __strong NSString *yourString = @"Your String"; 2 __weak NSString *myString = yourString; 3 yourString = nil; 4 __unsafe_unretained NSString *theirString = myString; 5 //现在所有的指针都为nil 再看一个: 1 __strong NSString *yourString = @"Your String"; 2 __weak NSString *myString = yourString; 3 __unsafe_unretained NSString *theirString = myString; 4 yourString = nil; 5 //现在yourString与myString的指针都为nil,而theirString不为nil,但是是野指针。 __autoreleasing的用法介绍: 在c/c++,objective-c内存管理中有一条是:谁分配谁释放。 __autoreleasing则可以使对像延迟释放。比如你想传一个未初始 化地对像引用到一个方法当中,在此方法中实始化此对像,那么这种情况将是__autoreleasing表演的时候。看个示例: 1 - (void) generateErrorInVariable:(__autoreleasing NSError **)paramError{ 2 NSArray *objects = [[NSArray alloc] initWithObjects:@"A simple error", nil]; 3 NSArray *keys = [[NSArray alloc] initWithObjects:NSLocalizedDescriptionKey, nil]; 4 NSDictionary *errorDictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys]; 5 *paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary]; 6 } 7 -(void)test 8 { 9 NSError *error = nil; 10 [self generateErrorInVariable:&error]; 11 NSLog(@"Error = %@", error); 12 } 这样即便在函数内部申请的空间,在函数外部也可以使用,同样也适合谁分配谁释放的原则。 同样下面的代码也是类似原因, 只不过在没有开启ARC的情况下适用: 1 -(NSString *)stringTest 2 { 3 NSString *retStr = [NSString stringWithString:@"test"]; 4 5 return [[retStr retain] autorelease]; 6 } 开启ARC后,应改为: 1 -(NSString *)stringTest 2 { 3 __autoreleasing NSString *retStr = [NSString alloc] initWithString:@"test"]; 4 5 return retStr; 6 }
相关推荐
在编程世界中,C语言因其低级特性而被广泛用于系统级编程,其中包括内存管理。内存管理是程序设计中的核心部分,它涉及到如何有效地分配、使用和释放内存资源。本主题将深入探讨如何使用C语言来实现内存管理的关键...
C#内存管理机制 C#内存管理机制是C#编程语言中的一种机制,旨在帮助程序员更好地管理内存资源。在C#中,程序员不需要手动管理内存,因为垃圾收集器会处理所有的内存清理工作。但是,了解C#内存管理机制仍然非常重要...
在计算机科学领域,内存管理是程序设计中的一个关键部分,特别是在高级编程语言中。动态内存管理允许程序在运行时请求和释放内存,提高了程序的灵活性。本项目关注的是连续动态内存管理,具体实现了一个基于“首次...
文将对 Linux™ 程序员可以使用的内存管理技术进行概述,虽然关注的重点是 C 语言,但同样也适用于其他语言。文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半...
Linux内存管理是操作系统的核心组成部分,它负责有效地分配和回收内存资源,确保系统高效稳定地运行。在本实验中,我们主要探讨了Linux虚拟内存管理的原理、动态内存操作函数的使用,以及如何检测主存使用情况。 ...
操作系统内存管理是计算机科学中的核心领域,特别是在Linux这样的操作系统中,理解内存的分配、管理和优化至关重要。本实验报告聚焦于在Red Hat 9环境下进行的内存管理实践,旨在深入理解内存分片、分配策略以及其对...
操作系统内存管理是计算机科学中的核心概念,它涉及如何在多任务环境下有效地分配、使用和回收内存资源。在这个“操作系统内存管理实验(C语言实现)”中,我们将深入探讨这一主题,并通过C语言编写代码来模拟和理解...
Linux 内存管理源代码导读 Linux 内存管理是操作系统中最重要的组件之一,它负责管理计算机的内存资源,确保系统的正确运行。在 Linux 操作系统中,内存管理是通过页框管理、Slab 算法和动态存储器管理来实现的。 ...
在分析glibc内存管理的ptmalloc源代码之前,我们需要先了解一些基础知识,包括操作系统对内存的分配和管理方法,以及glibc内存分配机制。 内存管理是操作系统的一个核心功能,它负责维护和管理计算机系统中的物理和...
C++内存管理是编程领域中的一个关键话题,尤其对于C++开发者来说,它既是挑战,也是机遇。内存管理是C++复杂性和灵活性的核心,既能让经验丰富的程序员获得高性能和自由,也可能让初学者陷入无尽的调试困扰。由于C++...
整个内存管理系统可以分为2部分来看待: 第一部分是对物理内存的管理, 第二部分是对虚拟内存的管理. 物理内存管理的对象是板载的物理内存(DDRAM), 它把物理内存按页划分, 并把这些页放到一个池子里面. 物理内存管理...
模拟内存管理程序 本实验的目的是了解简单的固定大小内存分配方法,掌握分区存储管理技术,了解在分区管理机制下所需的数据结构。通过模拟内存管理程序,学生可以学习如何设计和实现一个基本的内存管理系统,包括...
### Linux源代码分析之内存管理 #### 摘要与关键词 本文档是对Linux内核内存管理系统的一个深入分析,特别是针对其源代码进行了详细的解读。Linux的内存管理是内核中最复杂的部分之一,它涉及到了内存初始化、地址...
在这个“操作系统课程设计内存管理”项目中,我们看到开发者使用了Microsoft Foundation Classes (MFC)库,这是一个C++类库,由微软为Windows应用程序开发设计。MFC简化了用户界面、数据库访问和网络编程等任务,但...
这份"内存管理源代码"提供了深入理解内存管理机制的宝贵资料,对于想要自己编写操作系统或者正在改进无内存管理系统的人来说,具有很高的参考价值。 在操作系统设计中,内存管理的目标主要有三个:防止内存碎片、...
Linux操作系统内存管理 Linux操作系统的内存管理是计算机科学中一个重要的领域。本文将详细阐述Linux操作系统的内存管理机制,包括物理内存和虚拟内存的管理机制、地址映射机制、内存碎片和内存不连续的问题解决等...
内存管理是计算机科学中的核心概念,特别是在编程语言如C++中。动态分区内存管理是一种用于在程序运行时分配和释放内存的方法,它允许程序根据需要动态地调整内存使用。本主题将深入探讨动态分区内存管理的基本原理...
操作系统中的内存管理是计算机系统设计的关键部分,它涉及到如何有效地分配、使用和回收内存资源,以确保多个进程的高效运行和系统的稳定性。在这个实习作业中,我们将深入探讨内存管理的基本概念和技术。 首先,...