前言:
ARC也有一些缺点,对于初学者来说,可能仅只能将ARC用在objective-c对象上(也即继承自NSObject的对象),但是如果涉及到较为底层的东西,比如Core Foundation中的malloc()或者free()等,ARC就鞭长莫及了,这时候还是需要自己手动进行内存管理。在之后我们会看到一些这方面的例子。另外为了确保ARC能正确的工作,有些语法规则也会因为ARC而变得稍微严格一些。
ARC确实可以在适当的地方为代码添加retain或者release,但是这并不意味着你可以完全忘记内存管理,因为你必须在合适的地方把strong指针手动设置到nil,否则app很可能会oom。简单说还是那句话,你必须时刻清醒谁持有了哪些对象,而这些持有者在什么时候应该变为指向nil。
开篇
一般说来我们使用OC代码,一般有两大特性:
- 使用类继承NSObject
- 上下文需要手动创建和释放
这里面其实涉及到一些内存管理的东西,可能平时没有去注意到:
下面举个例子:
- NSObject对象
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
- 上下文
//创建create
CG_EXTERN CGContextRef __nullable CGBitmapContextCreate(void * __nullable data,
size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow,
CGColorSpaceRef cg_nullable space, uint32_t bitmapInfo)
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
//释放release
/* Equivalent to `CFRelease(c)'. */
CG_EXTERN void CGContextRelease(CGContextRef cg_nullable c)
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
从上面可以看出,我们使用NSObject对象,系统会帮我们在合适的时候插入retain和release;自己手动调用CF的函数时候,函数由于不是继承NSObject,需要我们自己手动去释放;
补充点C++函数的知识:
函数
C++ 中的函数定义的一般形式如下:
return_type function_name( parameter list )
{
body of the function
}
在 C++ 中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:
- 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
- 函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
- 参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
- 函数主体:函数主体包含一组定义函数执行任务的语句。
函数声明
函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数声明包括以下几个部分:
return_type function_name( parameter list );
针对上面定义的函数 max(),以下是函数声明:
int max(int num1, int num2);
在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int max(int, int);
当您在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。在这种情况下,您应该在调用函数的文件顶部声明函数。
类的创建和释放
- malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
- 对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
- 因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
- C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
- new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void指针。
其实上面这么多:想说的只有一个,内存管理如果用NSObject那就不需要您手动搞了,如果用C++那就需要您手动释放掉内存了
[xxx new]和[xxx alloc]init]区别
There are a bunch of reasons here: http://macresearch.org/difference-between-alloc-init-and-new
Some selected ones are:
- new
doesn't support custom initializers (like initWithString) - alloc-init
is more explicit than new
General opinion seems to be that you should use whatever you're comfortable with.
总结:new只会调用默认的init方法,如果想NSString这种重写了initWithString就不适用了.
MRC和ARC混编的一些设置
如果MRC文件要放在ARC环境下编译,要标明不使用ARC进行编译
网友评论