iOS开发中 new与alloc/init的区别 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的区别

本文详细解析Objective-C中new与alloc/init的区别,包括内存分配、初始化过程,以及如何正确使用避免内存泄漏。同时,介绍了self与_的区别、懒加载的概念,以及如何在开发中应用这些知识进行高效内存管理。

项目过程中,想到这几个概念的区别有些模糊,于是纵观各种资料,来篇博文为自己记录下,也为小伙伴们说说我的理解。

[className new] 和 [[className alloc] init] 的区别

1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init]

但是并不意味着你不会接触到new,在一些代码中还是会看到[[className alloc] init]

还有去面试的时候,也很可能被问到这个问题。


2.那么,他们两者之间到底有什么区别呢

我们看源码:

  1. new 
  2. id newObject = (*_alloc)((Class)self, 0); 
  3. Class metaClass = self->isa; 
  4. if (class_getVersion(metaClass) > 1) 
  5. return [newObject init]; 
  6. else 
  7. return newObject; 
  8.  
  9. //而 alloc/init 像这样: 
  10. + alloc 
  11. return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());  
  12. - init 
  13. return self; 

通过源码中我们发现,[className new]基本等同于[[className alloc] init]

区别只在于alloc分配内存的时候使用了zone.

这个zone是个什么东东呢?

它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度;

3.而为什么不推荐使用new?

不知大家发现了没有:如果使用new的话,初始化方法被固定死只能调用init.

而你想调用initXXX怎么办?没门儿!据说最初的设计是完全借鉴Smalltalk语法来的。

传说那个时候已经有allocFromZone:这个方法,

但是这个方法需要传个参数id myCompanion = [[TheClass allocFromZone:[self zone]] init];

这个方法像下面这样:

  1. + allocFromZone:(void *) z 
  2. return (*_zoneAlloc)((Class)self, 0, z);  
  3.  
  4. //后来简化为下面这个: 
  5. + alloc 
  6. return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());  

但是,出现个问题:这个方法只是给对象分配了内存,并没有初始化实例变量。

是不是又回到new那样的处理方式:在方法内部隐式调用init方法呢?

后来发现“显示调用总比隐式调用要好”,所以后来就把两个方法分开了。

概括来说,new和alloc/init在功能上几乎是一致的,分配内存并完成初始化。

差别在于,采用new的方式只能采用默认的init方法完成初始化,

采用alloc的方式可以用其他定制的初始化方法。



再来说一个突然想起来的问题:[NSArray array] [[NSArray alloc]init] (包括字典等同类) 的使用方法的区别:


alloc (内存分配)以及init(初始化) Objective-C 协议分为非正式协议和正式协议 .

这两个方式都是建立一个空的Array
[NSArray array]不需要release,使用autoreleasepool机制。
[[NSArray alloc] init]需要自己手动release


项目使用崩溃实例:


在ViewDidLoad中   
jsonDataDic = [NSMutableDictionary dictionary];    
[self jsonParse];
创建一个空字典,在jsonParse中使用了这个词典,导致程序崩溃
解决方法:在jsonDataDic前面加上self.即可
原因:不加的话,指针的作用域仅在ViewDidLoad中,进入jsonParse后该指针已释放,成为了一个野指针,再对其进行操作,使程序崩溃。
注意:字典是没有顺序的,字典的allkeys或者allvalues存放到数组中是随机的。

总结:


new做的事情和alloc init是一样的,当然你要构造方法是init的时候完全可以用new来代替 ,alloc 不仅仅可以使用init构造方法,更可以自定义构造方法e.g initWithFrame等等。
另外,alloc开辟空间后能够自动清空新开辟内存空间中的老数据,不会出现莫名奇妙的错误,见《Objective-C基础教程》


说到这个问题,可能有小伙伴又懵了,那 self. _ 有什么区别呢,再说下这两个 :

( - -!没完了)


self.programStack等于[self programStack],会走你的懒加载方法;而_programStack类似于self->_programStack。

用self点出属性是更好的选择,因为这样可以兼容懒加载,同时也避免了使用下划线的时候忽视了self这个指针,后者容易在block中造成循环引用。


科普:懒加载(Load On Demand)是一种独特而又强大的数据获取方法,它能够在用户滚动页面的时候自动获取更多的数据,而新得到的数据不会影响原有数据的显示,同时最大程度上减少服务器端的资源耗用。


这两种使用方式显然是不一样的。


主要是涉及到内存管理的问题。self.propertyName 使用self. 是对属性的访问。使用_ 是对局部变量的访问。
所有被声明为属性的成员,在ios5 之前需要使用编译器指令@synthesize 来告诉编译器帮助生成属性的getter,setter方法。之后这个指令可以不用人为指定了,默认情况下编译器会帮我们生成。 编译器在生成getter,setter方法时是有优先级的,它首先查找当前的类中用户是否已定义属性的getter,setter方法,如果有,则编译器会跳过,不会再生成,使用用户定义的方法。 也就是说你在使用self.propertyName 时是在调用一个方法。


_______________________________________________________哥哥爱开发_________________________________________________________________

本篇博文有查询资料中大神的理论引用,有自己的原创理解,只为整理在一起方便理解。

最后:开发,只为简单生活,技术改变世界!~yeah~

代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统中修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程中所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统中,网络配置的管理机制早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此类问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
代码转载自:https://pan.quark.cn/s/46fd08fb879c 网管教程 从入门到精通软件篇 ★一。★详尽的xp修复控制台指令及其应用!!! 放入xp(2000)的光盘,安装时选择R,执行修复! Windows XP(涵盖 Windows 2000)的控制台指令是在系统遭遇某些意外状况时的一种极具效用的诊断、检测以及恢复系统功能的工具。笔者确实一直期望能够将这方面的指令进行归纳,此次由老范辛苦整理了这份极具价值的秘籍。 Bootcfg bootcfg 命令用于启动配置故障恢复(对大多数计算机而言,即 boot.ini 文件)。 带有特定参数的 bootcfg 命令仅在运用故障恢复控制台时方可使用。能够在命令行界面下运用带有不同参数的 bootcfg 命令。 用法: bootcfg /default 设定默认引导选项。 bootcfg /add 向引导清单中增添 Windows 安装。 bootcfg /rebuild 重复整个 Windows 安装流程并让用户选择需添加的项目。 注意:运用 bootcfg /rebuild 之前,应先借助 bootcfg /copy 命令备份 boot.ini 文件。 bootcfg /scan 探查用于 Windows 安装的全部磁盘并展示结果。 注意:这些结果被静态存储,并用于当前会话。若在当前会话期间磁盘配置发生变动,为获取更新的探查结果,必须先重启计算机,然后再次探查磁盘。 bootcfg /list 列示引导清单中已有的项目。 bootcfg /disableredirect 在启动引导程序中禁用重定向。 bootcfg /redirect [ PortBaudRrate] |[ useBio...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值