iOS與OS X多線程和內(nèi)存管理(二)Blocks

前言

上篇文章整理了關(guān)于“內(nèi)存管理”的知識點,這篇主要整理“Blocks”的內(nèi)容救恨,在學(xué)習(xí)Blocks的內(nèi)容時忿薇,我一開始也采取了學(xué)習(xí)“內(nèi)存管理”時采用的先閱讀《iOS與OS X多線程和內(nèi)存管理》再配合《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法 》署浩,但是在學(xué)習(xí)《iOS與OS X多線程和內(nèi)存管理》時有些理解比較困難扫尺,恰恰《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法 》中的內(nèi)容雖然比較少弊攘,但對閱讀《iOS與OS X多線程和內(nèi)存管理》中的內(nèi)容很有幫助,當(dāng)然還有別的學(xué)習(xí)途徑迈倍。以下內(nèi)容如有理解錯誤的地方啼染,希望大家指出迹鹅,我們一起學(xué)習(xí)和探討~

什么是blocks

BIocks是C語言的擴充功能贞言,可概括為:帶有自變量值的(局部變量)的匿名函數(shù)(匿名函數(shù)就是不帶名稱的函數(shù))

  • C語言的函數(shù)中可能使用的變量

    • 自動變量(局部變量)
    • 函數(shù)的參數(shù)
    • 靜態(tài)變量(靜態(tài)局部變量)
    • 靜態(tài)全局變量
    • 全局變量
  • 在函數(shù)的多次調(diào)用之間能夠傳遞值的變量(雖然這些變量的作用域不同弟蚀,但在整個程序中粗梭,一個變量總保持在一個內(nèi)存區(qū)域断医,所以雖然多次調(diào)用函數(shù)奏纪,該變量值總保持不變)

    • 靜態(tài)變量(靜態(tài)局部變量)
    • 靜態(tài)全局變量
    • 全局變量
  • C++和OC使用類可保持變量值且能夠多次持有該變量自身序调,它會聲明持有成員變量的類发绢,有類生成的實例或?qū)ο蟊3衷摮蓡T變量的值

  • ‘帶有自變量值的的匿名函數(shù)’這一個概念不僅指Blocks边酒,它還存在于其他許多程序語言中墩朦,在計算機科學(xué)中,次概念也稱為‘閉包(closure)’陋气、‘lambda’


    FD8CBA1E-3A58-48D1-8DE9-1BDD7061F00D.png

Blocks模式

Block語法(Block表達式語法)

  • Block語法與函數(shù)的不同

    • 沒有函數(shù)名
    • 帶有 ‘^’
  • Block語法(無省略)

3B1C4EF3D014B48AC387BB30F4EF3B19.png
   ^int (int count){return count + 1;}
//表達式中含有return語句時,其類型必須與返回值類型相同
  • Block語法(省略返回值類型)
EBD14914984DE1B285DDDC1D77552435.png
   ^ (int count){return count + 1;}
//省略返回值類型時晶渠,如果表達式中有return語句就使用該返回值的類型,如果表達式中沒有return語句就是void類型便瑟,表達式中含有多個return語句時到涂,所以return的返回值類型必須相同
  • Block語法(省略返回值類型践啄、參數(shù)列表)
71CC51D2A6B5806002181794275456AE.png
//不使用參數(shù)的Block語法
 ^void (void){ }
//省略后表達式為
 ^{ }

Block類型變量

  • 在Block語法下昭灵,可將Block語法賦值給聲明為Block類型的變量中烂完,即代碼中一旦使用Block語法就相當(dāng)于生成了可賦值給Block類型變量的‘值’

  • Blocks中由Block語法生成的值也被稱為‘Block’

  • Block即指代碼中的Block語法诵棵,又指由Block語法所生成的值

  • 聲明Block類型變量

  int (^blk)(int);
返回類型(^變量名)(參數(shù))
  • Block類型的變量用途
    • 自動變量
    • 函數(shù)參數(shù)
    • 靜態(tài)變量
    • 靜態(tài)全局變量
    • 全局變量
  //-使用Block語法將Block賦值為Block類型變量
  int(^blk)(int) = ^int(int count){return count + 1;};

  //由Block類型變量向Block類型變量賦值
  int(^blk1)(int) = blk嘶窄;
  
  int(^blk2)(int)柄冲;
  blk2 = blk1储耐;

  //在函數(shù)參數(shù)中使用Block類型變量可以函數(shù)傳遞Block(值)
  void fun(int(^blk)(int)){
    
  }

  //在函數(shù)返回值中指定Block類型,可以將Block作為函數(shù)的返回值返回
   int(^func())int{
        return ^(int count){return count + 1;};
    }

  //使用  typedef 
  typedef int(^blk_t) int;
  //原記述方式
  void fun(int(^blk)(int)){
  }
  //等價于
  void fun(int(blk_t blk){
  }

  //原記述方式
    int(^func())int{
        return ^(int count){return count + 1;};
    }
  //等價于
  blk_t func{
  }

截獲自動變量值

  • ‘帶有自動變量值’在Blocks中表現(xiàn)為‘截獲自動變量值’
  int main{
    int day = 256;
    int val = 10;
    const char *fmt = "val = %d\n";
    void (^ blk)(void) = ^{
        printf(fit , val);
     };
    
    val = 2;
    fmt = "There values were changed . val = %d\n";
    blk();
    return 0;
  }

  /*
    *Block語法的表達式使用的是它之前聲明的自動變量fmt和val
    *Blokcs中,Block表達式中截獲所使用的自動變量的值得哆,即Block表達式保存該自動變量的瞬間值
    *執(zhí)行Block語法后贩据,即使改寫B(tài)lock中使用的自動變量也不會影響B(tài)lock執(zhí)行時自定變量的值
    *結(jié)果輸出 val = 10饱亮;
    */

_ _block說明符

  • 自動變量的值截獲只能保存執(zhí)行Block語法瞬間的值近上,保存后就不能改寫該值
  int val = 0;
  void (^blk)(void) = ^{ val = 1;};
  blk();
  printf("val = %d\n");

  //編譯報錯
  • 如果想在Block語法表達式中將值賦給Block語法外聲明的自動變量(例如:val)壹无,需要在該自動變量上附加_ _block說明符
  _ _block int val = 0;
  void (^blk)(void) = ^{ val = 1;};
  blk();
  printf("val = %d\n");

  //結(jié)果輸出:val = 1斗锭;
  • 使用附有_ block說明符在自動變量可以在Block中賦值,該變量稱為 _block變量

截獲自動變量

   id array = [[NSMutableArray alloc] init];
   void (^blk) (void) = ^{
        id obj = [[NSObject alloc] init];
        [arrray addObject:obj];
    }
    /*
     *編譯不會報錯
     *代碼中截獲的是變量值為NSMutableArray類的對象(即截獲的是NSMutableArray類對象用的結(jié)構(gòu)體實例指針)
     *截獲OC對象帮毁,調(diào)用變更改對象的方法(addObject)作箍,即使用截獲對象不會出現(xiàn)任何錯誤
     */

   id array = [[NSMutableArray alloc] init];
   void (^blk) (void) = ^{
        array = [[NSMutableArray alloc] init];
    }
    /*
     *編譯報錯
     *向截獲的變量array賦值會產(chǎn)生編譯錯誤
     */

    _ _block id array = [[NSMutableArray alloc] init];
   void (^blk) (void) = ^{
        array = [[NSMutableArray alloc] init];
    }
    //編譯成功

Blocks實現(xiàn)

Block的實質(zhì)

  • Block即為Object_C的對象
  • C語言中有一下存儲類的說明符
    • typedef
    • extern
    • static(作為靜態(tài)變量存儲在數(shù)據(jù)區(qū))
    • auto(表示作為自動變量存儲在棧中)
    • register

Block存儲域

  • Block轉(zhuǎn)換為Block的結(jié)構(gòu)體類型自動變量
  • _ block變量轉(zhuǎn)換為 _block變量的結(jié)構(gòu)體類型自動變量
  • 結(jié)構(gòu)體類型的自動變量,即棧上生成的該結(jié)構(gòu)體的實例
1E0C18A7-FB73-4E72-95D8-5C30B2AD01DA.png
  • Block也是OC對象阶剑,該Block的類


    FDA8982E-C03A-46CE-8321-AE8D4E28DC85.png
C9F96C19-10DF-4D5B-99BC-EA3B465B377D.png
  • 記述全局變量的地方有Block語法時牧愁、Bolck語法的表達式中不使用應(yīng)截獲的自動變量時猪半,Block為_NSConcreteGlobalBlock類的對象,即Block配置的程序的數(shù)據(jù)區(qū)域中
  • 除上述情況Block配置的程序的棧上
    -配置在全局變量上的Block沽甥,從變量的作用域外也可以通過指針安全使用
  • 配置在棧上的Block摆舟,如果其所屬的變量作用域結(jié)束恨诱,該Block就被廢棄照宝,由于_ _block變量也配置在棧上硫豆,同理笼呆。
2C9642D6-9F9B-439F-8D37-D88C197E1787.png
  • Blocks提供了將Block和_ _block變量從棧上復(fù)制到堆上的方法來解決,將配置在棧上的Block復(fù)制到堆上秸弛,這樣即使Block語法記述的作用域結(jié)束递览,堆上的Block還是可以繼續(xù)存在(ARC有效,自動生成將Block從棧上復(fù)制到堆上)
01674628-B6AD-4843-888A-23DDC7D2E66B.png

_ _block變量存儲域

  • Block從棧中復(fù)制到堆上時镜雨,_ _block變量也會受影響(下圖)
image
  • 若在1個Block中使用_ block變量,當(dāng)該Block從棧中復(fù)制到堆上菲盾,使用的所有 block變量也必定配置在棧上懒鉴,這些 block變量也全部被從棧中復(fù)制到堆上,此時奴璃,Block持有堆 _block變量溺健,即使在該Block已被復(fù)制在堆上的情況下钮蛛,復(fù)制Block也對所使用的_block變量沒有任何影響(下圖)
    3FD99E0A-F6A2-4C4B-AEC0-98089992EEBC.png
  • 在多個Block中使用_ block變量時岭辣,因為最先會將所有的Bolck配置在棧上甸饱,所以 block變量也會配置在棧上叹话,在任何一個Block從棧復(fù)制到堆時驼壶, block變量也會一并從棧中復(fù)制到堆并被該Block所持有,當(dāng)剩下的Block從棧中復(fù)制到堆時泵喘,被復(fù)制的Block持有 block變量(之前復(fù)制到堆上的)纪铺,并增加 _block變量的引用計數(shù)(下圖)

    65B9DA56-8EC4-41CB-BE34-0884FC1F45E3.png

  • 如果配置在堆上的Block被廢棄鲜锚,那么它所使用的_ block變量也就被釋放(同理引用計數(shù)式內(nèi)存管理烹棉,使用 block變量的Block持有 block變量浆洗,如果Block被廢棄伏社,它所持有的 _block變量也就被釋放)(下圖)

    723DF0DA-B19B-4D66-8A64-1FD9129DEDD8.png

  • Block的_ _main_block_impl_0結(jié)構(gòu)體實例持有指向 _ _block變量的 _ _Block_dyref_val_0結(jié)構(gòu)體實例指針
  • _ _Block_dyref_val_0結(jié)構(gòu)體實例的成員變量 _ _forwarding持有指向該實例自身的指針摘昌,通過成員變量 _ _forwarding訪問成員變量val(成員變量val是該實例自身持有的變量,它相當(dāng)于原自動變量)
66FC9034-763C-412F-AE51-070DFA21666E.png
  • 不管_ block變量配置在棧上還是堆上罕容,都能夠正確的訪問該變量(通過Block的復(fù)制锦秒,_ block變量也從棧上復(fù)制到堆旅择,此時可同時訪問棧上的 block變量和堆上的 _block變量)
    • 棧上的_ block變量用結(jié)構(gòu)體實例在 _block變量從棧復(fù)制到堆上時生真,會將成員變量 _ forwarding的值替換為復(fù)制目標(biāo)堆上 _block變量用結(jié)構(gòu)體實例的地址
    • 通過該功能柱蟀,無論是在Block語法中产弹,Block語法外使用弯囊,_ block變量匾嘱,還是 block變量配置在棧上還是堆上霎烙,都可以順利訪問同一個 _block變量悬垃。
BF70ABC0-60DC-4C31-9550-41EB64317008.png

截獲對象

  • 生成并持有NSMutableArray類的對象尝蠕,由于附有_strong修飾符的賦值目標(biāo)變量作用域立即結(jié)束看彼,所以對象也被立即釋放并廢棄
    id array = [[NSMutableArray alloc] init];
  • 在Block語法中使用該變量array
    blk_t blk;
    {
        id array = [[NSMutableArray alloc] init];
        blk = [^(id obj){
            [array addObjct:obj];
            NSLog(@"array count = %ld",[array coun]);
      } copy];
    }
    blk ([[NSObject alloc] init]);
    blk ([[NSObject alloc] init]);
    blk ([[NSObject alloc] init]);

    //輸出結(jié)果
    array count = 1
    array count = 2
    array count = 3

   /*
    *輸出結(jié)果意味著,賦值給變量array的NSMutableArray類的對象在該源代碼最后Block的執(zhí)行部分超出變量作用域而存在
    *被賦值NSMutableArray類對象并被截獲的自動變量array标锄,它是Block用的結(jié)構(gòu)體中附有_strong修飾符的成員變量
    struct _main_block_impl_0{
      struct _block_impl impl;
      struct _main_block_desc_0 *Desc;
      id strong array;
    }
    *Block用結(jié)構(gòu)體中料皇,還有附有_strong修飾符的對象類型變量array践剂,所以需要恰當(dāng)管理賦值給變量array的對象舷手,因此_main_block_copy_0函數(shù)使用_Block_object_assjgn函數(shù)將對象類型對象賦值給Block用結(jié)構(gòu)體的成員變量array中并持有該對象
    *_Block_object_assjgn函數(shù)調(diào)用相當(dāng)一retain實例方法函數(shù)男窟,將對象賦值給對象類型的結(jié)構(gòu)體成員變量中
    *_main_block_dispose_0函數(shù)使用_Block_object_dispose函數(shù)贾富,釋放賦值在Block用結(jié)構(gòu)體成員變量array中的對象颤枪,相當(dāng)于release實例方法畏纲,釋放賦值在對象類型結(jié)構(gòu)體成員變量中的對象
    */
  • 在Block從棧復(fù)制到堆時以及堆上的Block被廢棄時會調(diào)用的函數(shù)
4203D13C-5B6B-4073-8AD2-942AB2D2A890.png
  • 什么時候棧上的Block會復(fù)制到堆盗胀?

    • 調(diào)用Blcok的coyp實例方法時(如果Block配置在棧上票灰,那么該Block會從棧上復(fù)制到堆)
    • Block作為函數(shù)返回值返回時(編譯器自動的將對象的Block作為參數(shù)并調(diào)用_Block_cpoy函數(shù)-等同與copy實例方法)
    • 將Block賦值給附有_strong修飾符id類型的類或Block類型成員變量時(編譯器自動的將對象的Block作為參數(shù)并調(diào)用_Block_cpoy函數(shù)-等同與copy實例方法)
    • 在方法名中含有usingBlock的Cocoa框架方法或GrandCentralDispatch的API中傳遞Block時(該方法或函數(shù)內(nèi)部對傳遞過來的Block調(diào)用Block的copy實例方法或_Block_cpoy函數(shù))
  • 上述情況下棧上的Block被復(fù)制到堆上屑迂,其實實質(zhì)是_Block_cpoy函數(shù)被調(diào)用時Block從棧上復(fù)制到堆
    -在釋放復(fù)制到堆上的Block后,誰都不持有Blcok而是其被廢棄時調(diào)用despose函數(shù)庸汗,相當(dāng)于對象的release實例方法

  • 綜上所述夫晌,通過使用附有_strong修飾符的自動變量,Block中截獲的對象就能夠超出其變量的作用域而存活

  • 截獲對象時和使用_ _block對象時copy函數(shù)或dispose函數(shù)的不同

4888C201-5B2E-4BB5-A492-8463000A0CA7.png
  • 通過BLOCK_FIELD_IS_OBJECT和BLOCK_FIELD_IS_BYREF參數(shù)所袁,區(qū)分copy函數(shù)和dispose函數(shù)的對象類型時對象還是_ _block變量
  • 與copy函數(shù)持有截獲的對象燥爷,dispose函數(shù)釋放截獲的對象相同前翎,copy函數(shù)持有所使用的_ block變量港华,dispose函數(shù)釋放所使用的 _block變量
  • Block中使用的賦值給附有strong修飾符的自動變量的對象和復(fù)制到堆上的 _block變量由于被堆上的Block所持有立宜,因而可超出其作用域而存在
  • 只有調(diào)用_Block_cpoy函數(shù)才能持有截獲的附有_strong修飾符的對象類型的自動變量值臊岸,如果沒有調(diào)用_Block_cpoy函數(shù)帅戒,即使截獲了對象,它也會隨著變量的作用域結(jié)束而被廢棄
  • Block 中使用對象類型自動變量時钟哥,除以下情況外腻贰,推薦調(diào)用Block的copy實例方法
    • Blcok作為函數(shù)返回值返回時
    • 將Block賦值給類的附有_strong修飾符的id類型或Block類型成員變量時
    • 在方法名中含有usingBlock的Cocoa框架方法或GrandCentralDispatch的API中傳遞Block時

_ _block變量和對象

  • _ _block說明符可指定任何類型的自動變量

  • 在Block賦值給附有_strong修飾符的id類型或?qū)ο箢愋妥詣幼兞康那闆r下,當(dāng)Block從棧中復(fù)制到堆時践盼,使用_Block_object_assjgn函數(shù)咕幻,持有Block截獲的對象,到堆上的Block被廢棄時锣吼,使用_Block_object_dispose函數(shù)函數(shù),釋放Block截獲的對象

  • 在_ _block變量為附有strong修飾符的id類型或?qū)ο箢愋妥詣幼兞康那闆r下古徒,當(dāng) _block變量從棧中復(fù)制到堆時读恃,使用Block_object_assjgn函數(shù)寺惫,持有賦值給 block變量的對象西雀,到堆上的 _block變量被廢棄時,使用Block_object_dispose函數(shù)函數(shù)腔呜,釋放賦值給 _block變量的對象

  • 即使對象賦值復(fù)制到堆上的附有strong修飾符的對象類型 block變量中育谬,只有 _block變量在堆上繼續(xù)存在膛檀,那么該對象就會繼續(xù)處于被持有的狀態(tài)

  • 在Block語法中使用該變量array

    blk_t blk;
    {
        id array = [[NSMutableArray alloc] init];
        id _ _weak array2 = array;
        _ _block id _ _weak array3 = array;
        blk = [^(id obj){
            [array2 addObjct:obj];
            NSLog(@"array2 count = %ld娘侍,array2 count = %ld",[array2 coun]憾筏,[array3 coun]);
      } copy];
    }
    blk ([[NSObject alloc] init]);
    blk ([[NSObject alloc] init]);
    blk ([[NSObject alloc] init]);

    //輸出結(jié)果
    array2 count = 0 array3 count = 0
    array2 count = 0 array3 count = 0
    array2 count = 0 array3 count = 0


   /*
    *由于附有_strong修飾符的變量array在該變量作用域結(jié)束的同時釋放氧腰、廢棄,nil被賦值在附有_ _weak修飾符的變量array2中箩帚,即使附加 _ _block修飾符附有_strong修飾符的變量array在該變量作用域結(jié)束的同時釋放紧帕、廢棄是嗜,nil被賦值在附有_ _weak修飾符的變量array3中
    */

Block循環(huán)引用

  • 通過_weak修飾符,避免循環(huán)引用
typedef void (^blk_t) (void);

@interface MyObject : NSObject
{
    blk_t blk_;
}
@end


@implementation MyObject

-(id)init{
    self = [super init];
    blk_ = ^{ NSLog(@"self = %@", self); }
    return self;
}

-(void)dealloc{
    NSLog(@"dealloc");
}

@end

int mian(){
    id o = [[MyObject alloc] init];
    NSLog(@"%@", o );
    return o;
}

/*
 * MyObject類的dealloc實例方法一定沒有被調(diào)用
 * MyObject類對象的Block類型成員變量blk_持有賦值為Block的強引用(MyObject類對象持有Block)
 *init實例方法中執(zhí)行的Block語法使用附有_strong修飾符的id類型變量self
 *由于Block語法賦值在成員變量blk_中站绪,通過Block語法生成在棧上的Block此時有棧復(fù)制在堆上崇众,并持有所使用的self航厚,self持有Block幔睬,Block持有self,形成循環(huán)引用
 */
D7124496FF78DECEAC96909FD5C49DCF.jpg
  • 為避免此循環(huán)赦抖,可聲明附有_weak修飾符的變量队萤,并將self賦值使用
-(id)init{
    self = [super init];
    id _ _weak tmp = self;
    blk_ = ^{ NSLog(@"self = %@", tmp); }
    return self;
}
F2598D7757C5843EE46FC8CFA534C296.jpg
  • 由于Block存在時要尔,持有該Block的Myobject類對象即復(fù)制在變量tmp中的self必定存在赵辕,因此不需要判斷變量tmp的值是否為nil

  • 使用_ _block變量來避免循環(huán)引用

typedef void (^blk_t) (void);

@interface MyObject : NSObject
{
    blk_t blk_;
}
@end


@implementation MyObject

-(id)init{
    self = [super init];
    _ _block id tmp = self;
    blk_ = ^{
         NSLog(@"self = %@", tmp);
         tmp = nil;
    }
    return self;
}

-(void)execBlock{
  blk_();
}
-(void)dealloc{
    NSLog(@"dealloc");
}

@end

int mian(){
    id o = [[MyObject alloc] init];
    [o execBlock];
    return o;
}

  • 不執(zhí)行execBlock實例方法还惠,即不執(zhí)行賦值給成員變量blk_的Block蚕键,會引起循環(huán)引用引起的內(nèi)存泄露锣光,存在循環(huán)引用:
    • MyObject類對象持有Block
    • Block持有 _ _block 變量
    • _ _block變量持有MyObject類對象
2A6F5F4B537D7C2B4272E34F0E73A605.jpg
  • 執(zhí)行execBlock實例方法嫉晶,Block被實行田篇,nil被賦值在 _ _block 變量tmp中
    blk_ = ^{
         NSLog(@"self = %@", tmp);
         tmp = nil;
    }
 /*
  *_ _block 變量tmp對MyObject類對象的強引用失效,避免循環(huán)引用
  * MyObject類對象持有Block
  * Block持有 _ _block 變量
  */ 

AF9D11E4CFFC05E678884E0135F637DC.jpg

copy/release

  • ARC無效時椎镣,一般需要手動使用copy實例方法將Block從棧上復(fù)制到堆状答。通過release實例方法釋放復(fù)制的Block
  • 只要Block有一次復(fù)制并配置在堆上惊科,就可通過retain實例方法持有(但對于配置在棧上的Block調(diào)用retain實例方法則不起作用)
  • 在ARC無效時馆截,_ block說明符被用來避免循環(huán)引用蜂莉,這是由于當(dāng)Block從棧復(fù)制到堆時映穗,若Block使用的變量為附有 block說明符的id類型或?qū)ο箢愋偷淖詣幼兞浚粫籸etain宿接,若Block使用的變量為沒有 block說明符的id類型或?qū)ο箢愋偷淖詣幼兞砍窝簦瑒t會被retain(ARC有效或無效時 _block說明符的用途不同踏拜,要注意)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末速梗,一起剝皮案震驚了整個濱河市姻锁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拷窜,老刑警劉巖篮昧,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懊昨,死亡現(xiàn)場離奇詭異酵颁,居然都是意外死亡,警方通過查閱死者的電腦和手機幽污,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門油挥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來深寥,“玉大人贤牛,你說我怎么就攤上這事∪蚣” “怎么了武鲁?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵沐鼠,是天一觀的道長饲梭。 經(jīng)常有香客問我焰檩,道長,這世上最難降的妖魔是什么兜叨? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任国旷,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘特漩。我一直安慰自己骨杂,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布蛤售。 她就那樣靜靜地躺著悴能,像睡著了一般漠酿。 火紅的嫁衣襯著肌膚如雪炒嘲。 梳的紋絲不亂的頭發(fā)上匈庭,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天阱持,我揣著相機與錄音,去河邊找鬼啼止。 笑死献烦,一個胖子當(dāng)著我的面吹牛卖词,可吹牛的內(nèi)容都是我干的吏夯。 我是一名探鬼主播噪生,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼跺嗽,長吁一口氣:“原來是場噩夢啊……” “哼桨嫁!你這毒婦竟也來了璃吧?” 一聲冷哼從身側(cè)響起废境,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤噩凹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后务冕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體禀忆,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡箩退,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年戴涝,在試婚紗的時候發(fā)現(xiàn)自己被綠了钻蔑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡可帽,死狀恐怖映跟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情球恤,我是刑警寧澤荸镊,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布躬存,位于F島的核電站优构,受9級特大地震影響钦椭,放射性物質(zhì)發(fā)生泄漏碑诉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一德挣、第九天 我趴在偏房一處隱蔽的房頂上張望快毛。 院中可真熱鬧,春花似錦唠帝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轩褐,卻和暖如春玖详,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劳澄。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工秒拔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人作谚。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓妹懒,卻偏偏與公主長得像双吆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子好乐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

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