Object-C使用类静态方法创建对象时容易内存泄露
2015-04-05 18:39
369 查看
1.所谓使用类的静态方法创建对象,就是指使用类名调用一次它的静态方法(非显式调用alloc)便可以得到一个新建的对象,比如下面两个例子:
NSString* str1 = [NSString stringWithString:@"hello world"];
NSMutableString* str2 = [NSMutableString stringWithString:@"hello world"];
2. 第一个例子是使用字符串的字面常量"hello world"创建一个NSString对象,已知常量在编译期分配,存放在程序的数据区(常量区),全局唯一且不可改变;因为NSString对象是不可变的,所以str1直接指向数据区的"hello world",而不会在内存中创建副本;而str2是可变的字符串对象,因此需要将常量“hello world”的内容拷贝到内存,这样才支持对字符串内容的修改。因此,str1的创建基本上不增加内存开销,而str2的创建会增加内存开销。注意,如果以[NSString stringWithFormat:@"hello world %d",i]这种方式创建字符串对象,则也需要增加内存拷贝,他先把常量"hello world %d"拷贝到内存,然后替换掉%d,然后赋给新建的字符串对象。
3.NSString的静态方法stringWithString会创建一个对象,为了保证该对象能够被正确释放,在返回该对象之前,会调用对象的autorelease方法,将对象的释放操作交给了外层的自动释放池对象;而对应的经典的alloc+init方式创建的对象,不会调用autorelease.因为当你显式使用alloc时,ARC会给你添加相应的release操作,所以这种方式创建的对象可以被正常释放。
4.内存泄露的例子
使用死循环是为了使泄露的结果更更显,如果每次操作的数据很大,那效果更明显。
5.泄露的原因
每次创建对象str,都会开辟一块新内存存放数据"hello world";而释放的方式是autorelease,然而在此循环中接触不到外层的自动释放池,因此所有创建的对象都没有被及时释放掉,因此内存占用会越来越大,效果如同内存泄露。
6.解决方式
一:循环内使用自动释放池,及时释放掉对象(不推荐,增加自动释放池对象创建和销毁开销)
二:使用经典的alloc+init方式创建对象(推荐,效率高而无副作用)
三:如果可能,使用NSString代替NSMutableString(不推荐,勉强规避)
NSString* str1 = [NSString stringWithString:@"hello world"];
NSMutableString* str2 = [NSMutableString stringWithString:@"hello world"];
2. 第一个例子是使用字符串的字面常量"hello world"创建一个NSString对象,已知常量在编译期分配,存放在程序的数据区(常量区),全局唯一且不可改变;因为NSString对象是不可变的,所以str1直接指向数据区的"hello world",而不会在内存中创建副本;而str2是可变的字符串对象,因此需要将常量“hello world”的内容拷贝到内存,这样才支持对字符串内容的修改。因此,str1的创建基本上不增加内存开销,而str2的创建会增加内存开销。注意,如果以[NSString stringWithFormat:@"hello world %d",i]这种方式创建字符串对象,则也需要增加内存拷贝,他先把常量"hello world %d"拷贝到内存,然后替换掉%d,然后赋给新建的字符串对象。
3.NSString的静态方法stringWithString会创建一个对象,为了保证该对象能够被正确释放,在返回该对象之前,会调用对象的autorelease方法,将对象的释放操作交给了外层的自动释放池对象;而对应的经典的alloc+init方式创建的对象,不会调用autorelease.因为当你显式使用alloc时,ARC会给你添加相应的release操作,所以这种方式创建的对象可以被正常释放。
4.内存泄露的例子
while(YES) { NSMutableString* str = [NSMutableString stringWithString:@"hello world"]; }
使用死循环是为了使泄露的结果更更显,如果每次操作的数据很大,那效果更明显。
5.泄露的原因
每次创建对象str,都会开辟一块新内存存放数据"hello world";而释放的方式是autorelease,然而在此循环中接触不到外层的自动释放池,因此所有创建的对象都没有被及时释放掉,因此内存占用会越来越大,效果如同内存泄露。
6.解决方式
一:循环内使用自动释放池,及时释放掉对象(不推荐,增加自动释放池对象创建和销毁开销)
while(YES) { @autorelease{ NSMutableString* str = [NSMutableString stringWithString:@"hello world"]; } }
二:使用经典的alloc+init方式创建对象(推荐,效率高而无副作用)
while(YES) { NSMutableString* str = [[NSMutableString alloc]initWithString:@"hello world"]; }
三:如果可能,使用NSString代替NSMutableString(不推荐,勉强规避)
while(YES) { NSString* str = [NSString stringWithString:@"hello world"]; }
相关文章推荐
- java 程序加载过程---3--类中申明同时申明类的静态对象 创建类的实例 访问类的静态变量 调用类的静态方法 使用反射方法 初始化类的子类对象 直接使用java.exe 调用某个类
- 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器
- 静态工厂方法创建对象
- 惊天大秘诀之一,supermap object 对象使用方法,soRecordset
- Java网络编程从入门到精通(2):创建InetAddress对象的四个静态方法
- python创建只读属性对象的方法(ReadOnlyObject)
- 【spring notes】 使用静态工厂方法创建Bean
- 由多个Object(以Teacher为例)对象所形成的数组可以使用Arrays.sort方法进行排序(编号由低到高排序)。
- Javascript访问Cookie的四个基本方法无论是在创建页面还是构建对象都会使用到,单独拿出来备用:
- 学习effective java-1创建和销毁对象之静态工厂方法
- 创建InetAddress对象的四个静态方法
- Java网络编程从入门到精通(2):创建InetAddress对象的四个静态方法
- javascript:利用Object.create()方法创建对象
- 创建和销毁对象--考虑用静态工厂方法代替构造函数
- 使用反射-动态创建对象及调用对象方法
- 第05章 CORE C++_对象的创建和使用_继承_多态_析构_xxx_cast_友元_只读成员_静态成员_多重继承_虚继承_内部类
- JavaScript对象创建的几种方式及使用方法
- object对象的hasOwnProperty propertyIsEnumerable两个方法的使用
- synchronized 静态 非静态 方法 使用不同锁对象
- Javascript创建自定义对象 创建Object实例添加属性和方法