一.寫在前面的話
今天在寫代碼的過程中意外的見到了奇怪的現(xiàn)象岳遥,經(jīng)過深層的剖析發(fā)現(xiàn)這一部分知識還很有用未荒,所以就寫了一篇文章來記錄哩罪。
二.代碼演示
1.有如下視圖控制器
#import "ViewController.h"
#import "Student.h"
@interface ViewController ()
/*
這是一個(gè)學(xué)生的對象 用assign修飾 = =
實(shí)際開發(fā)中不建議用assign修飾對象
這么做的目的 是為了觀察對象是否被釋放
*/
@property (nonatomic, assign) Student *student;
@end
@implementation ViewController
//控制器中有個(gè)按鈕 按鈕點(diǎn)擊后就會執(zhí)行該方法
- (IBAction)buttonAction:(id)sender {
//點(diǎn)擊按鈕執(zhí)行方法
//讓學(xué)生學(xué)習(xí)
[self.student study];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
2.在ViewDidLoad中執(zhí)行 代碼1
self.student = [[Student alloc] init];
[self.student study];
執(zhí)行結(jié)果1
3.在ViewDidLoad中執(zhí)行 代碼2
Student *student = [[Student alloc] init];
self.student = student;
[student study];
執(zhí)行結(jié)果2
4.點(diǎn)擊按鈕 引發(fā)崩潰
三.引出問題
為什么兩個(gè)代碼中的student都是用assign修飾呀狼,而執(zhí)行結(jié)果卻一個(gè)崩潰一個(gè)順利執(zhí)行了呢等曼?
看到這里如果知道答案的朋友有兩個(gè)選擇里烦,如果覺得這是個(gè)低級問題或沒有用直接點(diǎn)擊瀏覽器左上角關(guān)閉,如果覺得還有點(diǎn)看頭就請繼續(xù)禁谦,如果文章有錯(cuò)誤給您造成不良反應(yīng)本人概不負(fù)責(zé) = =
四.揭曉答案
本人特別不喜歡賣關(guān)子胁黑,我的博客重來不進(jìn)行探究猜測直接揭曉我的結(jié)論
1.為什么一個(gè)崩潰 一個(gè)順利執(zhí)行
因?yàn)?code>代碼1中的student在執(zhí)行study方法前就被釋放了,原因是assign在對象釋放后不會對指針做任何處理州泊,所以當(dāng)對象釋放了這個(gè)指針就是野指針
丧蘸,向野指針
發(fā)送消息必然崩潰,代碼2中的對象為什么沒有崩潰呢拥诡,原因很簡單触趴,它執(zhí)行方法的時(shí)候?qū)ο蟛]有被釋放氮发,點(diǎn)擊按鈕后為什么會崩潰,原因很簡單冗懦,因?yàn)閷ο笤邳c(diǎn)擊按鈕之前已經(jīng)釋放了爽冕。
2.為什么代碼1中對象會被提前釋放
答案其實(shí)很簡單,這是ARC處理的潛規(guī)則披蕉,如果[[Student alloc] init]
前面是一個(gè)用assign修飾的屬性self.student
颈畸,就會發(fā)生接收后立即被釋放的情況,但如前面是 Student * student
就不會立刻被釋放没讲,而是出作用域
后被釋放眯娱,而作用域即為ViewDidLoad方法,出了這個(gè)方法就會被釋放爬凑。
3.ARC中代碼做了哪些操作讓對象釋放呢
這里復(fù)習(xí)一下ARC的原理徙缴,即編譯器會在編譯過程中自動(dòng)向代碼中插入release和autorelease等語句,自動(dòng)管理對象的內(nèi)存嘁信, 這里說明一下release的作用是讓對象引用計(jì)數(shù)-1于样,而autorelease的作用是當(dāng)對象出自動(dòng)釋放池或作用域時(shí)讓對象引用計(jì)數(shù)-1,當(dāng)對象引用計(jì)數(shù)為0時(shí)潘靖,就會調(diào)用對象本身的dealloc方法釋放內(nèi)存穿剖。
為了證明這一觀點(diǎn),我們切換到MRC模式下進(jìn)行代碼演示
代碼1中系統(tǒng)做的操作是
self.student = [[Student alloc] init];
[self.student release];
[self.student study];
執(zhí)行結(jié)果是:
與代碼1中崩潰信息一致 即向野指針發(fā)送消息程序崩潰
代碼2中系統(tǒng)所做的操作是
Student *student = [[Student alloc] init];
[student autorelease];
self.student = student;
[student study];
執(zhí)行結(jié)果是:
點(diǎn)擊按鈕后發(fā)生崩潰
這與代碼2中的現(xiàn)象一樣卦溢,所以可以證實(shí)我的結(jié)論是正確的
以上觀點(diǎn)為個(gè)人推理所得糊余,如果有任何疑問或發(fā)現(xiàn)了錯(cuò)誤,請及時(shí)與我聯(lián)系单寂,歡迎朋友們積極踴躍糾正我的錯(cuò)誤贬芥。