iOS開發(fā) -- ARC與引用計數(shù)

以下是關(guān)于內(nèi)存管理的學(xué)習(xí)筆記:引用計數(shù)ARC者蠕。
iOS5以前自動引用計數(shù)(ARC)是在MacOS X 10.7與iOS 5中引入一項(xiàng)新技術(shù)帅涂,用于代替之前的手工引用計數(shù)MRC(Manual Reference Counting)管理Objective-C中的對象【官方也叫MRR(Manual Retain Release)】摔寨。如今省店,ARC下的iOS項(xiàng)目幾乎把所有內(nèi)存管理事宜都交給編譯器來決定涤浇,而開發(fā)者只需專注于業(yè)務(wù)邏輯。
但是例朱,對于iOS開發(fā)來說孝情,內(nèi)存管理是個很重要的概念,如果先要寫出內(nèi)存使用效率高而又沒有bug的代碼洒嗤,就得掌握其內(nèi)存管理模型的細(xì)節(jié)箫荡。

一、引用計數(shù)

1.與內(nèi)存管理的關(guān)系渔隶?

在Objective-C內(nèi)存管理中羔挡,每個對象都有屬于自己的計數(shù)器:如果想讓某個對象繼續(xù)存活(例如想對該對象進(jìn)行引用),就遞增它的引用計數(shù)派撕;當(dāng)用完它之后婉弹,就遞減該計數(shù);當(dāng)沒人引用該對象终吼,它的計數(shù)變?yōu)?之后镀赌,系統(tǒng)就把它銷毀。
這個际跪,就是引用計數(shù)在其中充當(dāng)?shù)慕巧河糜诒硎井?dāng)前有多少個對象想令此對象繼續(xù)存活程序中商佛;

2.引用計數(shù)的介紹:

引用計數(shù)(Reference Count)喉钢,也叫保留計數(shù)(retain count),表示對象被引用的次數(shù)良姆。一個簡單而有效的管理對象生命周期的方式肠虽。

3.引用計數(shù)的工作原理:

當(dāng)我們創(chuàng)建(alloc)一個新對象A的時候,它的引用計數(shù)從零變?yōu)?1玛追;
當(dāng)有一個指針指向這個對象A税课,也就是某對象想通過引用保留(retain)該對象A時帽哑,引用計數(shù)加 1琐鲁;
當(dāng)某個指針/對象不再指向這個對象A,也就是釋放(release)該引用后损谦,我們將其引用計數(shù)減 1陆馁;
當(dāng)對象A的引用計數(shù)變?yōu)?0 時找颓,說明這個對象不再被任何指針指向(引用)了,這個時候我們就可以將對象A銷毀叮贩,所占內(nèi)存將被回收击狮,且所有指向該對象的引用也都變得無效了。系統(tǒng)也會將其占用的內(nèi)存標(biāo)記為“可重用”(reuse)益老;

流程參考圖如下:


(圖片表格取自《編寫高質(zhì)量iOS與OS X代碼的52個有效方法》一書)

4.操作引用計數(shù)的那些方法:

A.以下是NSObject協(xié)議中聲明的3個用于操作計數(shù)器的方法:

retain : 保留彪蓬。保留計數(shù)+1;
release : 釋放杨箭。保留計數(shù) -1寞焙;
autorelease :稍后(清理“自動釋放池”時),再遞減保留計數(shù)互婿,所以作用是延遲對象的release;

B.dealloc方法:

另外辽狈,當(dāng)計數(shù)為0的時候?qū)ο髸詣诱{(diào)用dealloc慈参。而我們可以在dealloc方法做的,就是釋放指向其他對象的引用刮萌,以及取消已經(jīng)訂閱的KVO驮配、通知;(自己不能調(diào)用dealloc方法着茸,因?yàn)檫\(yùn)行期系統(tǒng)會在恰當(dāng)?shù)臅r候調(diào)用它壮锻,而且一旦調(diào)用dealloc方法,對象不再有效涮阔,即使后續(xù)方法再次調(diào)用retain猜绣。)
所以,調(diào)用release后會有2種情況:
調(diào)用前計數(shù)>1敬特,計數(shù)減1掰邢;
調(diào)用前計數(shù)<1牺陶,對象內(nèi)存被回收;

C.retainCount:獲取引用計數(shù)的方法辣之。

Eg: [object retainCount]; //得到object的引用計數(shù)

retain掰伸、autorelease、release方法詳解

retain作用:

調(diào)用后計數(shù)+1怀估,保留對象操作狮鸭。但是當(dāng)對象被銷毀、內(nèi)存被回收的時候多搀,即使使用retain也不再有效怕篷;

autorelease作用:

autorelease不立即釋放,而是注冊到autoreleasepool(自動釋放池)中酗昼,等到pool結(jié)束時釋放池再自動調(diào)用release進(jìn)行釋放工作廊谓。
autorelease看上去很像ARC,但是實(shí)際上更類似C語言中的自動變量(局部變量)麻削,當(dāng)某自動變量超出其作用域(例如大括號)蒸痹,該自動變量將被自動廢棄,而autorelease中對象實(shí)例的release方法會被調(diào)用呛哟;[與C不同的是叠荠,開發(fā)者可以設(shè)定變量的作用域。]
釋放時間:每個Runloop中都創(chuàng)建一個Autorelease pool(自動釋放池)扫责,每一次的Autorelease榛鼎,系統(tǒng)都會把該Object放入了當(dāng)前的Autorelease pool中,并在Runloop的末尾進(jìn)行釋放鳖孤,而當(dāng)該pool被釋放時者娱,該pool中的所有Object會被調(diào)用Release。 所以苏揣,一般情況下黄鳍,每個接受autorelease消息的對象,都會在下個Runloop開始前被釋放平匈。
例如可用以下場景:(需要從ARC改為使用手動管理的可以做如下的設(shè)置: 在Targets的Build Phases選項(xiàng)下Compile Sources下選擇要不使用ARC編譯的文件框沟,雙擊它,輸入-fno-objc-arc即可使用MRC手工管理內(nèi)存方式增炭;)

-(NSString *)getSting{ 
  NSString *str = [[NSString alloc]initWithFormat:@"I am Str"];
  return [str autorelease];
}

自動釋放池中的釋放操作會等到下一次時間循環(huán)時才會執(zhí)行忍燥,所以調(diào)用以下:

NSString *str = [self getSting];NSLog(@"%@",str);

返回的str對象得以保留,延遲釋放隙姿。因此可以無需再NSLog語句之前執(zhí)行保留操作梅垄,就可以將返回的str對象輸出。
所以可見autorelease的作用是能延長對象的生命期孟辑。使其在跨越方法調(diào)用邊界后依然可以存活一段時間哎甲。

release作用:

release會立即執(zhí)行釋放操作蔫敲,使得計減1;
有這樣一種情況:當(dāng)某對象object的引用計數(shù)為1的時候炭玫,調(diào)用“[object release];”奈嘿,此時如果再調(diào)用NSLog方法輸出object的話,可能程序就會崩潰吞加,當(dāng)然只是有可能裙犹,因?yàn)閷ο笏純?nèi)存在“解除分配(deallocated)”之后,只是放回“可用內(nèi)存池(avaiable pool)”衔憨,但是如果執(zhí)行NSLog時叶圃,尚未覆寫對象內(nèi)存,那么該對象依然有效践图,所以程序有可能不會崩潰掺冠,由此可見,因過早地釋放對象而導(dǎo)致的bug很難調(diào)試码党。
為避免這種情況德崭,一般調(diào)用完對象之后都會清空指針:"object = nil",這樣就能保證不會出現(xiàn)指向無效對象的指針揖盘,也就是懸掛指針(dangling pointer);
懸掛指針:指向無效對象的指針眉厨。

那么,向已經(jīng)釋放(dealloc)的對象發(fā)送消息兽狭,retainCount會是多少憾股?

原則是不可以這么做。因?yàn)樵搶ο蟮膬?nèi)存已經(jīng)被回收箕慧,而我們向一個已經(jīng)被回收的對象發(fā)了一個 retainCount 消息服球,所以它的輸出結(jié)果應(yīng)該是不確定的,例如為減少一次內(nèi)存的寫操作销钝,不將這個值從 1 變成 0有咨,所以很大可能輸出1。例如下面這種情況:

Person *person = [[Person alloc] init]; //此時蒸健,計數(shù) = 1   
[person retain];  //計數(shù) = 2  
[person release];  //計數(shù) = 1   
[person release]; //很可能計數(shù) = 1;  

雖然第四行代碼把計數(shù)1release了一次,原理上person對象的計數(shù)會變成0婉商,但是實(shí)際上為了優(yōu)化對象的釋放行為似忧,提高系統(tǒng)的工作效率,在retainCount為1時release系統(tǒng)會直接把對象回收丈秩,而不再為它的計數(shù)遞減為0盯捌,所以一個對象的retainCount值有可能永遠(yuǎn)不為0;
因此蘑秽,不管是否為ARC的開發(fā)環(huán)境中饺著,也不推薦使用retainCount來做為一個對象是否存在于內(nèi)存之中的依據(jù)箫攀。
<br /><br />


二、ARC

1.背景:

ARC是iOS 5推出的新功能幼衰,全稱叫 ARC(Automatic Reference Counting)靴跛。
即使2014 年的 WWDC 大會上推出的Swift 語言,該語言仍然使用 ARC 技術(shù)作為其管理方式渡嚣。

2.ARC是什么梢睛?

需要注意的是,ARC并不是GC(Garbage Collection 垃圾回收器)识椰,它只是一種代碼靜態(tài)分析(Static Analyzer)工具绝葡,背后的原理是依賴編譯器的靜態(tài)分析能力,通過在編譯時找出合理的插入引用計數(shù)管理代碼腹鹉,從而提高iOS開發(fā)人員的開發(fā)效率藏畅。
Apple的文檔里是這么定義ARC的:
“自動引用計數(shù)(ARC)是一個編譯器級的功能,它能簡化Cocoa應(yīng)用中對象生命周期管理(內(nèi)存管理)的流程功咒∮溲郑”

3.ARC在做什么?

在編譯階段航瞭,編譯器將在項(xiàng)目代碼中自動為分配對象插入retain诫硕、release和autorelease,且插入的代碼不可見刊侯。
但是章办,需要注意的是,ARC模式下引用計數(shù)規(guī)則還起作用滨彻,只是編譯器會為開發(fā)者分擔(dān)大部分的內(nèi)存管理工作藕届,除了插入上述代碼,還有一部分優(yōu)化以及分析內(nèi)存的管理工作亭饵。
作用:
a.降低內(nèi)存泄露等風(fēng)險 休偶;
b.減少代碼工作量,使開發(fā)者只需專注于業(yè)務(wù)邏輯辜羊;

4.ARC具體為引用計數(shù)做了哪些工作踏兜?

編譯階段自動添加代碼:

編譯器會在編譯階段以恰當(dāng)?shù)臅r間與地方給我們填上原本需要手寫的retain、release八秃、autorelease等內(nèi)存管理代碼碱妆,所以ARC并非運(yùn)行時的特性,也不是如java中的GC運(yùn)行時的垃圾回收系統(tǒng)昔驱;因此疹尾,我們也可以知道,ARC其實(shí)是處于編譯器的特性。
例如:

-(void)setup{ 
   _person = [person new];
}

在手工管理內(nèi)存的環(huán)境下纳本,_person是不會自動保留其值窍蓝,而在ARC下編譯,其代碼會變成:

-(void)setup{ 
  person *tmp = [person new];
  _person = [tmp retain]; 
  [tmp release];
}

當(dāng)然繁成,在開發(fā)工作中吓笙,retain和release對于開發(fā)人員來說都可以省去,由ARC系統(tǒng)自動補(bǔ)全朴艰,達(dá)到同樣的效果观蓄。
但實(shí)際上,ARC系統(tǒng)在自動調(diào)用這些方法時祠墅,并不通過普通的Objective-C消息派發(fā)控制侮穿,而是直接調(diào)用底層C語言的方法:
比如retain,ARC在分析到某處需要調(diào)用保留操作的地方毁嗦,調(diào)用了與retain等價的底層函數(shù) objc_retain亲茅,所以這也是ARC下不能覆寫retain、release或者autorelease的原因狗准,因?yàn)檫@些方法在ARC從來不會被直接調(diào)用克锣。

運(yùn)行期組件的優(yōu)化:

ARC是編譯器的特性,但也包含了運(yùn)行期組件腔长,所執(zhí)行的優(yōu)化很有意義袭祟。
例子:
person工廠方法personWithName可以得到一個person對象,在這里調(diào)用并賦值給person的一個實(shí)例_one:

_one = [person personWithName:@"name"];

可能會出現(xiàn)這種情況:
在personWithName方法中捞附,返回對象給_one之前巾乳,為其調(diào)用了一次autorelease方法。
由于實(shí)例變量是個強(qiáng)引用鸟召,所以編譯器會在設(shè)置其值的時候還需要執(zhí)行一次保留操作胆绊。

//在personWithName方法返回前已有調(diào)用一次autorelease方法進(jìn)行保留操作;
person *tmp = [person personWithName:@"name"]; 

_one = [tmp retain];

很明顯欧募,autorelease與緊跟其后的retain是重復(fù)的压状。為提升性能,可以將二者刪去跟继,舍棄autorelease這個概念种冬,并且規(guī)定返回對象的技術(shù)都比期望值多1,但是為了向后兼容非ARC等情況.
ARC采取了另外一種方式:
ARC可以在運(yùn)行期檢測到這一對多余的操作舔糖。所以在返回對象時碌廓,不直接調(diào)用autorelease,改為調(diào)用objc_autoreleaseReturnValue剩盒,用來檢測返回之后即將要執(zhí)行的代碼中,含有retain操作,則設(shè)置全局?jǐn)?shù)據(jù)結(jié)構(gòu)(此數(shù)據(jù)結(jié)構(gòu)具體內(nèi)容因處理器而異)中的一個標(biāo)志位辽聊,而不執(zhí)行autorelease操作纪挎。
同樣,若方法返回一個自動釋放對象跟匆,調(diào)用personWithName方法的代碼段不執(zhí)行retain异袄,改為執(zhí)行objc_retainAutoreleaseReturnValue函數(shù)。此函數(shù)檢測剛才的那個標(biāo)志位玛臂,若已經(jīng)置位了烤蜕,則不執(zhí)行retain操作。

而設(shè)置并檢測標(biāo)志位迹冤,要比調(diào)用autorelease和retain更快讽营,這就使得這一情況的處理得到優(yōu)化。
修改2個函數(shù)后優(yōu)化完整結(jié)果如下: 【例子來自《編寫高質(zhì)量iOS與OS X代碼的52個有效方法》一書P126】


我們可以通過兩個函數(shù)的偽代碼大致描述如下:

像是
objc_autoreleaseReturnValue
這個函數(shù)是如何檢測方法調(diào)用者是否會立刻保留對象呢泡徙,這就要交給處理器來解決了橱鹏。
由于必須查看原始機(jī)器碼指令方可判斷出這一點(diǎn)需要處理器來定。
所以堪藐,其實(shí)只有編譯器的作者才能知道這里是如何實(shí)現(xiàn)此函數(shù)的莉兰。
ARC的安全性:
在編寫屬性的設(shè)置方法(setter)時,如果使用手工管理方式礁竞,可能會需要如下編寫:

-(void)setObject:(id)object{ 
   [_object release]; 
   _object = [object retain];
}

但是這樣寫會出現(xiàn)問題:如果說新值object和實(shí)例變量_object的值是相同的糖荒,而且只有當(dāng)前實(shí)例變量對象還在引用這個值,那么設(shè)置方法中的釋放操作會使得該值保留計數(shù)為0模捂,系統(tǒng)將其回收捶朵,所以接下來的保留操作,將會令應(yīng)用程序崩潰枫绅。而在使用ARC的環(huán)境下泉孩,就不可能會發(fā)送這樣的的“邊界情況”了:

剛才的代碼在ARC下可以這樣寫:(當(dāng)然,我們知道如果不需要覆寫setter方法并淋,也可以不編寫此方法寓搬,直接使用"self.object = xxx"也可以安全地調(diào)用。):

-(void)setObject:(id)object{ 
   _object = object;
}

而且ARC會用一種安全的方式來設(shè)置:先保留新值县耽,再釋放舊值句喷,最后設(shè)置實(shí)例變量。
在手工管理的情況下兔毙,我們需要特別注意這種"邊緣情況"唾琼,但是ARC下,我們就可以很輕松地編寫這種代碼了澎剥,而不用去考慮這種情況如何處理了锡溯。
總結(jié):將內(nèi)存管理交由編譯器運(yùn)行期組件來做,可以使代碼得到多種優(yōu)化,而上面是其中一種方式祭饭。

5.ARC下需要注意的規(guī)則

a.關(guān)于dealloc:
. 不能顯式調(diào)用dealloc芜茵;
. 不能再dealloc中調(diào)用【super dealloc】(非ARC下則需要調(diào)用.);
. 不能在dealloc 中釋放資源(非ARC下需要釋放不同的對象)倡蝙;
b.以及九串,不能顯式調(diào)用以下代碼:


(NSZone:內(nèi)存區(qū))

c.不能再使用NSAutoreleasePool對象,ARC提供了@autoreleasepool塊來代替它寺鸥,這樣更有效率猪钮;

6.所有權(quán)修飾符

oc編程中為了處理對象,可將變量類型定義為id類型或各種對象類型胆建。使用這些限定符可以確切地聲明對象變量和屬性的生命周期烤低;
所謂對象類型就是指向NSObject這樣的oc類的指針,例如“NSObject *”眼坏。id類型用于隱藏對象類型的類名部分拂玻。相當(dāng)于C語言中常用的“void *”;
ARC下宰译,id類型和對象類型上必須附加所有權(quán)修飾符檐蚜;
所有權(quán)修飾符一共有4種:
__strong:
強(qiáng)引用,可以引用別的對象為強(qiáng)引用沿侈,相當(dāng)于retain的特性闯第;表明變量持有alloc/new/copy/mutableCopy方法群創(chuàng)建的對象的強(qiáng)引用,強(qiáng)引用變量會在其作用域里被保留缀拭,在超出作用域后被釋放咳短,為默認(rèn)的修飾符;
例如以下代碼
id objc = [[NSObject alloc] init];
實(shí)際上已被附上所有權(quán)修飾符:
id __strong objc = [[NSObject alloc] init];

__weak:
使用__strong蛛淋,有可能2個對象相互強(qiáng)引用或者1個對象對自身強(qiáng)引用則會發(fā)生循環(huán)引用(如下圖咙好,或者叫保留環(huán)),所以當(dāng)對象在超出其生存周期后褐荷,本應(yīng)被系統(tǒng)廢棄卻仍然被引用者所持有勾效,所以造成內(nèi)存泄露(應(yīng)當(dāng)廢棄的對象在超出生命周期后,繼續(xù)存在)叛甫;

(2個對象互相強(qiáng)引用)
(某對象對自身強(qiáng)引用)

而當(dāng)我們對可能會發(fā)送循環(huán)引用的對象進(jìn)行__weak弱引用修飾层宫,弱引用變量不會持有對象,且生成的對象會立刻釋放其监,可避免循環(huán)引用萌腿,并且弱引用還有另外一個特點(diǎn),若對象被系統(tǒng)回收抖苦,該弱引用變量將自動失效并且賦值為nil毁菱。
__unsafe_unretained: 不安全的所有權(quán)修飾符米死,ARC的內(nèi)存管理是編譯器的工作,而附有__unsafe_unretained修飾符的變量不屬于編譯器的內(nèi)存管理對象鼎俘。與__weak作用一樣哲身,也可以避免循環(huán)引用;但是不同的是贸伐,__unsafe_unretained屬性的變量不會將變量設(shè)置為nil,而是就處于于懸掛狀態(tài)怔揩;

__autoreleasing:在ARC中使用“@autoreleasepool塊”來取代“NSAutoreleasePool”類對象的生成捉邢,通過將對象賦值給附加了__autoreleasing修飾符的變量來替代調(diào)用autorelease方法;

Other:ARC需要注意的事項(xiàng)商膊?

1.過度使用 block 之后伏伐,無法解決循環(huán)引用問題。
2.遇到底層 Core Foundation 對象晕拆,需要自己手工管理它們的引用計數(shù)時藐翎,我們需轉(zhuǎn)換關(guān)鍵字,作為橋接轉(zhuǎn)換以解決 Core Foundation 對象與 Objective-C 對象相對轉(zhuǎn)換的問題:
__bridge:使用__bridge標(biāo)記可以在不修改相關(guān)對象的引用計數(shù)的情況下实幕,將對象從Core Foundation框架數(shù)據(jù)類型轉(zhuǎn)換為Foundation框架數(shù)據(jù)類型(反之亦然)吝镣。
__bridge_retained:會將相關(guān)對象的引用計數(shù)加 1,并且可以將Core Foundation框架數(shù)據(jù)類型對象轉(zhuǎn)換為Foundation框架數(shù)據(jù)類型對象昆庇,并從ARC接管對象的所有權(quán)末贾。
__bridge_transfer:可以將Foundation框架數(shù)據(jù)類型對象轉(zhuǎn)換為Core Foundation框架數(shù)據(jù)類型對象,并且會將對象的所有權(quán)交給ARC管理整吆,也就是說引用計數(shù)交由ARC管理拱撵;

總結(jié):就推薦2本經(jīng)典的書(估計很多人早就看完了?? ),書本也好表蝙,pdf也好拴测,建議看一下:
《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法》
《Objective-C高級編程 iOS與OS X多線程和內(nèi)存管理》
<br />


(轉(zhuǎn)載請標(biāo)明原文出處,謝謝支持 ~ - ~)
? by:啊左~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末府蛇,一起剝皮案震驚了整個濱河市集索,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欲诺,老刑警劉巖抄谐,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扰法,居然都是意外死亡蛹含,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門塞颁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浦箱,“玉大人吸耿,你說我怎么就攤上這事】峥” “怎么了咽安?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蓬推。 經(jīng)常有香客問我妆棒,道長,這世上最難降的妖魔是什么沸伏? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任糕珊,我火速辦了婚禮,結(jié)果婚禮上毅糟,老公的妹妹穿的比我還像新娘红选。我一直安慰自己,他們只是感情好姆另,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布喇肋。 她就那樣靜靜地躺著,像睡著了一般迹辐。 火紅的嫁衣襯著肌膚如雪蝶防。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天右核,我揣著相機(jī)與錄音慧脱,去河邊找鬼。 笑死贺喝,一個胖子當(dāng)著我的面吹牛菱鸥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播躏鱼,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼氮采,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了染苛?” 一聲冷哼從身側(cè)響起鹊漠,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茶行,沒想到半個月后躯概,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畔师,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年娶靡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片看锉。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡姿锭,死狀恐怖塔鳍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情呻此,我是刑警寧澤轮纫,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站焚鲜,受9級特大地震影響掌唾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恃泪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一郑兴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贝乎,春花似錦、人聲如沸叽粹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虫几。三九已至锤灿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辆脸,已是汗流浹背但校。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啡氢,地道東北人状囱。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像倘是,于是被迫代替她去往敵國和親亭枷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容