Object-C使用类静态方法创建对象时容易内存泄露

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的创建会增加内存开销。

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"];
}
时间: 2024-08-07 17:11:34

Object-C使用类静态方法创建对象时容易内存泄露的相关文章

Object(所有类的超类)一些有用的方法讲解与实例演示

Object是所有类的始祖,java中的每个类的都是它拓展而来的. Object的euqals方法.hashCode方法.getClass方法和toString方法在操作对象时是非常有用的方法.     1.euqals方法      euqals方法用于检测一个对象是否等于另外一个对象(两个对象是否指向同一块存储区域),java语言规范要求euqals方法具有以下特性: 自反性.对称性.传递性.一致性并且对于任意的非空引用x,x.equals(null)应返回false. java7在java

编写高质量代码改善C#程序的157个建议——建议10: 创建对象时需要考虑是否实现比较器

建议10: 创建对象时需要考虑是否实现比较器 有对象的地方就会存在比较,在.NET的世界中也一样.举个最简单的例子,在UI中,有一个10个人的Salary列表.根据排序的需要,列表要支持针对基本工资来罗列Salary.这个时候,接口IComparable就会起作用,代码如下所示: class Salary : IComparable { public string Name { get; set; } public int BaseSalary { get; set; } public int

是否存在不继承自System.Object类型的类

分析问题 可能读者的固有思维认为.NET中所有的类型都必须继承自System.Object,这样的认识过于绝对,且不完全正确.在.NET中,.NET设计小组为中间语言的编译器ILasm.exe添加了noautoinherit开关,当这个开关被打开时,编译器将不会默认年地把类型认为继承自System.Object. 首先介绍一下中间语言的编译工具:ILasm.exe.这是.NET Framework提供的一个编译工具,它的作用是把中间语言(MSIL)编译成可执行的PE文件.该工具非常有用,它不仅使

js类定义函数时用不用prototype的区别?

一直在使用js编写自以为是面向对象的方法,遇到一个问题,就是定义一个方法,如下:      function ListCommon2(first,second,third) {   this.First=function () {  alert("first do"+first); } }  ListCommon2.do1=function(first) {    //   this.First();  alert("first do"+first); } List

eclipse环境Dynamic web module version 3.1版本的进步,简化Dynamic web object 中Servlet类的配置,不用web.xml配置<Servlet>

eclipse环境Dynamic web module version 3.1版本之前,Dynamic web object 中Servlet类的配置,要在web.xml 配置<Servlet>图片和代码如下: web.xml中源代码如下: <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-ins

第1章 类和对象——定义类和创建对象

1.1     定义类.创建对象 在编程时,要定义类,然后在创建这个类的对象(实例). 1.1.1 定义类 定义类的语法个式如下: 访问修饰符 Class 类名 {     类的成员1:     ................     类的成员n:       } 各项的含义如下. 1)  “访问修饰符”用来限制类的作用范围或访问级别,类的修饰符只有public和internal两种(嵌套类除外).其中,声明为public的类可以被任何其他类访问:声明为internal的类智只能从同一个程序集

【IOS 开发】Object - C 面向对象 - 类 , 对象 , 成员变量 , 成员方法

. 一. 类定义 类定义需要实现两部分 : -- 接口部分 : 定义类的成员变量和方法, 方法是抽象的, 在头文件中定义; -- 实现部分 : 引入接口部分的头文件, 实现抽象方法; 1. 接口部分定义 (1) 接口部分定义格式 接口部分定义格式 : @interface className : superClassName { type _variableName; ... ... } - (type) methodName : type parameterName; @end -- 接口定义

基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------&gt; 可以返回派生类对象的引用或指针

您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. 百度和网页 http://bbs.csdn.net/topics/380238133 的作者无关,不对其内容负责.百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面. 首页 精选版块 移动开发 iOS Android Qt WP 云计算 IaaS Pass/SaaS 分布式计算/Hadoop J

Python的类实例方法,类方法,类静态方法

以下面的类定义为例: # coding:utf-8 class A: count = 0 def __init__(self, inst_name): self.inst_name = inst_name self.__class__.count += 1 def inst_method(self): print '实例(%s):%s' % (self.__class__.count, self.inst_name) @classmethod def class_method(cls): pri