Objective-C copy,看我就夠了

一、從面向?qū)ο蟮絆bjective-C概覽copy

1稍算、面向?qū)ο螅?/h4>

In object-oriented programming, object copying is creating a copy of an existing object, a unit of data in object-oriented programming. The resulting object is called an object copy or simply copy of the original object. Copying is basic but has subtleties and can have significant overhead. There are several ways to copy an object, most commonly by a copy constructor or cloning. Copying is done mostly so the copy can be modified or moved, or the current value preserved. If either of these is unneeded, a reference to the original data is sufficient and more efficient, as no copying occurs.

在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,對(duì)象的copy就是創(chuàng)建一個(gè)已經(jīng)存在的對(duì)象的copy役拴。這種對(duì)象的創(chuàng)建的結(jié)果被稱(chēng)為原始對(duì)象的copy糊探。copy是很基礎(chǔ)的,但是也有其精巧的地方河闰,并且可能造成巨大的消耗科平。有很多種方式可以copy對(duì)象,最常用的就是copy構(gòu)造器和克隆姜性。copy經(jīng)常用于對(duì)象的修改瞪慧、移動(dòng)和保護(hù)。如果上述的幾種應(yīng)用都不需要部念,持有原始對(duì)象的引用就足夠了弃酌,并不需要copy氨菇。

2、OC:

In Objective-C, the methods copy and mutableCopy are inherited by all objects and intended for performing copies; the latter is for creating a mutable type of the original object. These methods in turn call the copyWithZone and mutableCopyWithZone methods, respectively, to perform the copying. An object must implement the corresponding copyWithZone method to be copyable.

在OC中矢腻,copy和mutableCopy兩個(gè)方法是被所有對(duì)象繼承的(有點(diǎn)小毛病门驾,應(yīng)該指所有繼承自NSObject的類(lèi))射赛,這兩個(gè)方法就是為copy準(zhǔn)備的多柑。其中,mutableCopy是為了創(chuàng)建原始對(duì)象的可變類(lèi)型的copy楣责。這兩個(gè)方法分別調(diào)用copyWithZone和mutableCopyWithZone兩個(gè)方法來(lái)進(jìn)行copy竣灌。一個(gè)類(lèi)必須實(shí)現(xiàn)copyWithZone或者mutableCopyWithZone,才能進(jìn)行copy或者mutableCopy秆麸。

那么初嘹,我們可以從以上獲取到什么信息?

  • copy經(jīng)常用于對(duì)象的修改、移動(dòng)和保護(hù)沮趣。如果上述的幾種應(yīng)用都不需要屯烦,持有原始對(duì)象的引用就足夠了,并不需要copy房铭。
  • 一個(gè)類(lèi)必須實(shí)現(xiàn)copyWithZone或者mutableCopyWithZone驻龟,才能進(jìn)行copy或者mutableCopy。

下一階段缸匪,本文將展開(kāi)講述OC中的copy相關(guān)信息以及如何使用copy方法翁狐。

二、Objective-C中copy相關(guān)

1凌蔬、OC中的copy相關(guān)內(nèi)容

  • 在XCode 里Foundation.framework下的Headers里露懒,也在系統(tǒng)里找到原文件:/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObject.h
@protocol NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
@end
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
@end
  • 在/usr/include/objc 下面找到 runtime 的 NSObject.h
- (id)copy;
- (id)mutableCopy;
  • 修飾屬性的關(guān)鍵字copy

2、這里需要注意的有以下幾點(diǎn)

  • 若想使用copymutableCopy砂心,需要分別實(shí)現(xiàn)NSCopying協(xié)議和NSMutableCopying協(xié)議懈词,即實(shí)現(xiàn)copyWithZone:mutableCopyWithZone:方法。
  • 繼承自NSObject的大部分框架類(lèi)均默認(rèn)實(shí)現(xiàn)了NSCopying辩诞,并且一些具備可變類(lèi)型的類(lèi)如NSString钦睡、NSArray、NSDictionary躁倒,以及它們的可變類(lèi)型類(lèi)NSMutableString荞怒、NSMutableArray和NSMutableDictionary也實(shí)現(xiàn)了NSMutableCopying。(查了大部分常用類(lèi)秧秉,均實(shí)現(xiàn)了NSCopying褐桌,所以暫時(shí)這么說(shuō)吧,可能有人說(shuō)NSNumber并沒(méi)有實(shí)現(xiàn)NSCopying象迎,那你可以看一下它的父類(lèi)NSValue荧嵌,其實(shí)現(xiàn)了NSCopying)
  • 對(duì)于一些自定義類(lèi)呛踊,需要自己實(shí)現(xiàn)NSCopying。具體方式且看下部分啦撮。

三谭网、非容器對(duì)象的深淺copy

首先,我們談一下非容器對(duì)象的深淺copy赃春,這些非容器對(duì)象愉择,包含常用的NSString、NSNumber等织中,也包括我們自定義的一些非容器類(lèi)的實(shí)例锥涕。下面分三個(gè)三面進(jìn)行分析。

1狭吼、首先說(shuō)說(shuō)深淺copy

準(zhǔn)則
淺copy:指針復(fù)制层坠,不會(huì)創(chuàng)建一個(gè)新的對(duì)象。
深copy:內(nèi)容復(fù)制刁笙,會(huì)創(chuàng)建一個(gè)新的對(duì)象破花。

此處,不進(jìn)行過(guò)多的解釋?zhuān)瑥南旅娴慕Y(jié)果分析中疲吸,按例子來(lái)理解座每。

2、框架類(lèi)的深淺copy

準(zhǔn)則
探究框架類(lèi)深copy還是淺copy磅氨,需要清楚的是該類(lèi)如何實(shí)現(xiàn)的NSCopying和NSMutableCopy的兩個(gè)方法copyWithZone:和mutableCopyWithZone:尺栖。然而OC并不開(kāi)源,并且本文這里也不會(huì)進(jìn)行源碼的推測(cè)烦租。
那么延赌,我們應(yīng)該遵循怎樣一個(gè)原則呢?如下:

  • 對(duì)immutableObject叉橱,即不可變對(duì)象挫以,執(zhí)行copy,會(huì)得到不可變對(duì)象窃祝,并且是淺copy掐松。
  • 對(duì)immutableObject,即不可變對(duì)象粪小,執(zhí)行mutableCopy大磺,會(huì)得到可變對(duì)象,并且是深copy探膊。
  • 對(duì)mutableObject杠愧,即可變對(duì)象,執(zhí)行copy逞壁,會(huì)得到不可變對(duì)象流济,并且是深copy锐锣。
  • 對(duì)mutableObject,即可變對(duì)象绳瘟,執(zhí)行mutableCopy雕憔,會(huì)得到可變對(duì)象,并且是深copy糖声。

代碼

// 此處以NSString為例探究框架類(lèi)深淺copy
    
// 不可變對(duì)象
NSString *str = @"1";
NSString *str1 = [str copy];
NSString *str2 = [str mutableCopy];
    
// 可變對(duì)象
NSMutableString *mutableStr = [NSMutableString stringWithString:@"1"];
NSMutableString *mutableStr1 = [mutableStr copy];
NSMutableString *mutableStr2 = [mutableStr mutableCopy];
    
// 打印對(duì)象的指針來(lái)確認(rèn)是否創(chuàng)建了一個(gè)新的對(duì)象
// 不可變對(duì)象原始指針
NSLog(@"%p", str);
// 不可變對(duì)象copy后指針
NSLog(@"%p", str1);
// 不可變對(duì)象mutalbeCopy后指針
NSLog(@"%p", str2);
    
// 可變對(duì)象原始指針
NSLog(@"%p", mutableStr);
// 可變對(duì)象copy后指針
NSLog(@"%p", mutableStr1);
// 可變對(duì)象mutalbeCopy后指針
NSLog(@"%p", mutableStr2);

結(jié)果分析

// 此處依次對(duì)應(yīng)上述6個(gè)log斤彼,可見(jiàn)與前面所講的原則吻合(此處不驗(yàn)證可變類(lèi)型和不可變類(lèi)型,默認(rèn)上述原則正確即可)姨丈。
2016-10-21 10:50:52.879 Memory[67680:5623387] 0x10d85a1b0
2016-10-21 10:50:52.879 Memory[67680:5623387] 0x10d85a1b0
2016-10-21 10:50:52.879 Memory[67680:5623387] 0x60800007a080
2016-10-21 10:50:52.879 Memory[67680:5623387] 0x60800007a9c0
2016-10-21 10:50:52.880 Memory[67680:5623387] 0xa000000000000311
2016-10-21 10:50:52.880 Memory[67680:5623387] 0x60800007a900

3畅卓、自定義類(lèi)的深淺copy

準(zhǔn)則
對(duì)于一個(gè)我們自定義的類(lèi)型擅腰,顯然比框架類(lèi)容易操縱的多蟋恬。此處就拿NSCopying舉例(因?yàn)閺臎](méi)有自定義過(guò)具有可變類(lèi)型的類(lèi),當(dāng)然趁冈,如果有需要的話歼争,也可以實(shí)現(xiàn)NSMutableCopying)。自定義的類(lèi)就和2中的原則沒(méi)有半毛錢(qián)關(guān)系了渗勘,一切就看你怎么實(shí)現(xiàn)NSCopying協(xié)議中的copyWithZone:方法沐绒。

代碼

// Model定義,copyWithZone第一種實(shí)現(xiàn)(淺copy)
@interface Model1 : NSObject <NSCopying>
@property (nonatomic, assign) NSInteger a;
@end

@implementation Model1
- (id)copyWithZone:(NSZone *)zone {
    return self;
}
@end

// Model定義旺坠,copyWithZone第二種實(shí)現(xiàn)(深copy)
@interface Model1 : NSObject <NSCopying>
@property (nonatomic, assign) NSInteger a;
@end

@implementation Model1
- (id)copyWithZone:(NSZone *)zone {
    Model1 *model = [[Model1 allocWithZone:zone] init];
    model.a = self.a;
    return model;
}
@end

// 分別選擇上述兩種model進(jìn)行指針打印乔遮。
Model1 *model = [[Model1 alloc] init];
Model1 *copyModel = [model copy];
    
NSLog(@"%p", model);
NSLog(@"%p", copyModel);

結(jié)果分析

// 對(duì)應(yīng)上述一,可見(jiàn)實(shí)現(xiàn)了淺copy
2016-10-21 11:12:03.149 Memory[67723:5636292] 0x60000000c9d0
2016-10-21 11:12:03.149 Memory[67723:5636292] 0x60000000c9d0
// 對(duì)應(yīng)上述二取刃,可見(jiàn)實(shí)現(xiàn)了深copy
2016-10-21 11:16:46.803 Memory[67752:5640133] 0x60800001df00
2016-10-21 11:16:46.803 Memory[67752:5640133] 0x60800001def0

四蹋肮、容器對(duì)象的深淺copy

前文已經(jīng)知道了深淺copy的區(qū)別,你也大致猜到了為什么將容器對(duì)象拿出來(lái)作為一塊璧疗。對(duì)坯辩,因?yàn)槿萜髦锌赡馨芏鄬?duì)象,而這些對(duì)象也需要區(qū)分深淺copy崩侠。往深里說(shuō)漆魔,容器中可能包含容器對(duì)象,那更是麻煩了却音。不要急改抡,看下面,以NSArray的深淺copy為例系瓢,將容器的深淺copy分為四種阿纤。

1、淺copy

準(zhǔn)則
容器的淺copy八拱,符合三.2中的原則阵赠。
代碼

// 和NSString淺copy的驗(yàn)證步驟一樣
NSArray *arr = [NSArray arrayWithObjects:@"1", nil];
NSArray *copyArr = [arr copy];
    
NSLog(@"%p", arr);
NSLog(@"%p", copyArr);

結(jié)果分析

// 無(wú)疑是淺copy(你可能會(huì)問(wèn)涯塔,為什么不看一下arr和copyArr內(nèi)部元素的指針對(duì)比?這里并沒(méi)有必要清蚀,最外層對(duì)象都沒(méi)有創(chuàng)建新的匕荸,里面不用驗(yàn)證)
2016-10-21 11:27:57.554 Memory[67778:5646253] 0x600000010690
2016-10-21 11:27:57.554 Memory[67778:5646253] 0x600000010690

2、單層深copy

準(zhǔn)則
容器的單層深copy枷邪,符合三.2中的原則(只是深copy變成了單層深copy)榛搔。這里的單層指的是完成了NSArray對(duì)象的深copy,而未對(duì)其容器內(nèi)對(duì)象進(jìn)行處理东揣。
代碼

NSArray *arr = [NSArray arrayWithObjects:@"1", nil];
NSArray *copyArr = [arr mutableCopy];
    
NSLog(@"%p", arr);
NSLog(@"%p", copyArr);
    
// 打印arr践惑、copyArr內(nèi)部元素進(jìn)行對(duì)比
NSLog(@"%p", arr[0]);
NSLog(@"%p", copyArr[0]);

結(jié)果分析

// 可發(fā)現(xiàn)前兩項(xiàng)地址不同,即完成深copy嘶卧,但是后兩項(xiàng)相同尔觉,這代表容器內(nèi)部的元素并沒(méi)有完成深copy,所有稱(chēng)之為單層深copy
2016-10-21 11:32:27.157 Memory[67801:5649757] 0x6000000030d0
2016-10-21 11:32:27.157 Memory[67801:5649757] 0x600000242e50
2016-10-21 11:32:27.157 Memory[67801:5649757] 0x10dd811b0
2016-10-21 11:32:27.157 Memory[67801:5649757] 0x10dd811b0

3芥吟、雙層深copy

準(zhǔn)則
容器的雙層深copy已經(jīng)脫離了三.2中的原則侦铜。這里的雙層指的是完成了NSArray對(duì)象和NSArray容器內(nèi)對(duì)象的深copy(為什么不說(shuō)完全,是因?yàn)闊o(wú)法處理NSArray中還有一個(gè)NSArray這種情況)钟鸵。
代碼

// 隨意創(chuàng)建一個(gè)NSMutableString對(duì)象
NSMutableString *mutableString = [NSMutableString stringWithString:@"1"];
// 隨意創(chuàng)建一個(gè)包涵NSMutableString的NSMutableArray對(duì)象
NSMutableString *mutalbeString1 = [NSMutableString stringWithString:@"1"];
NSMutableArray *mutableArr = [NSMutableArray arrayWithObjects:mutalbeString1, nil];
// 將mutableString和mutableArr放入一個(gè)新的NSArray中
NSArray *testArr = [NSArray arrayWithObjects:mutableString, mutableArr, nil];
// 通過(guò)官方文檔提供的方式創(chuàng)建copy
NSArray *testArrCopy = [[NSArray alloc] initWithArray:testArr copyItems:YES];
    
// testArr和testArrCopy指針對(duì)比
NSLog(@"%p", testArr);
NSLog(@"%p", testArrCopy);
    
// testArr和testArrCopy中元素指針對(duì)比
// mutableString對(duì)比
NSLog(@"%p", testArr[0]);
NSLog(@"%p", testArrCopy[0]);
// mutableArr對(duì)比
NSLog(@"%p", testArr[1]);
NSLog(@"%p", testArrCopy[1]);
    
// mutableArr中的元素對(duì)比钉稍,即mutalbeString1對(duì)比
NSLog(@"%p", testArr[1][0]);
NSLog(@"%p", testArrCopy[1][0]);

結(jié)果分析

// 這里可以發(fā)現(xiàn),copy后棺耍,只有mutableArr中的mutalbeString1指針地址沒(méi)有變化贡未。而testArr的指針和testArr中的mutableArr、mutableString的指針地址均發(fā)生變化蒙袍。所以稱(chēng)之為雙層深復(fù)制俊卤。
2016-10-21 12:03:15.549 Memory[67855:5668888] 0x60800003c7a0
2016-10-21 12:03:15.549 Memory[67855:5668888] 0x60800003c880
2016-10-21 12:03:15.549 Memory[67855:5668888] 0x608000260540
2016-10-21 12:03:15.550 Memory[67855:5668888] 0xa000000000000311
2016-10-21 12:03:15.550 Memory[67855:5668888] 0x60800005d610
2016-10-21 12:03:15.550 Memory[67855:5668888] 0x60800000d2e0
2016-10-21 12:03:15.550 Memory[67855:5668888] 0x608000260980
2016-10-21 12:03:15.550 Memory[67855:5668888] 0x608000260980

限制
initWithArray: copyItems:會(huì)使NSArray中元素均執(zhí)行copy方法。這也是我在testArr中放入NSMutableArray和NSMutableString的原因左敌。如果我放入的是NSArray或者NSString瘾蛋,執(zhí)行copy后,只會(huì)發(fā)生指針復(fù)制矫限;如果我放入的是未實(shí)現(xiàn)NSCopying協(xié)議的對(duì)象哺哼,調(diào)用這個(gè)方法甚至?xí)rash。這里叼风,官方文檔的描述有誤取董。

If the objects in the collection have adopted the NSCopying
protocol, the objects are deeply copied to the new collection, which is then the sole owner of the copied objects.

4、完全深copy

準(zhǔn)則
如果想完美的解決NSArray嵌套NSArray這種情形无宿,可以使用歸檔茵汰、解檔的方式。
代碼

// 隨意創(chuàng)建一個(gè)NSMutableString對(duì)象
NSMutableString *mutableString = [NSMutableString stringWithString:@"1"];
// 隨意創(chuàng)建一個(gè)包涵NSMutableString的NSMutableArray對(duì)象
NSMutableString *mutalbeString1 = [NSMutableString stringWithString:@"1"];
NSMutableArray *mutableArr = [NSMutableArray arrayWithObjects:mutalbeString1, nil];
// 將mutableString和mutableArr放入一個(gè)新的NSArray中
NSArray *testArr = [NSArray arrayWithObjects:mutableString, mutableArr, nil];
// 通過(guò)歸檔孽鸡、解檔方式創(chuàng)建copy
NSArray *testArrCopy = [NSKeyedUnarchiver unarchiveObjectWithData:
                            [NSKeyedArchiver archivedDataWithRootObject:testArr]];;
    
// testArr和testArrCopy指針對(duì)比
NSLog(@"%p", testArr);
NSLog(@"%p", testArrCopy);
    
// testArr和testArrCopy中元素指針對(duì)比
// mutableString對(duì)比
NSLog(@"%p", testArr[0]);
NSLog(@"%p", testArrCopy[0]);
// mutableArr對(duì)比
NSLog(@"%p", testArr[1]);
NSLog(@"%p", testArrCopy[1]);
    
// mutableArr中的元素對(duì)比蹂午,即mutalbeString1對(duì)比
NSLog(@"%p", testArr[1][0]);
NSLog(@"%p", testArrCopy[1][0]);

結(jié)果分析

// 可見(jiàn)完成了完全深復(fù)制栏豺,testArr和testArrCopy中的元素,以及容器中容器的指針地址完全不同豆胸,所以完成了完全深復(fù)制奥洼。
2016-10-21 12:19:34.022 Memory[67887:5677318] 0x60800002db00
2016-10-21 12:19:34.022 Memory[67887:5677318] 0x60800002dc20
2016-10-21 12:19:34.022 Memory[67887:5677318] 0x608000260400
2016-10-21 12:19:34.023 Memory[67887:5677318] 0x6080002603c0
2016-10-21 12:19:34.023 Memory[67887:5677318] 0x608000051d90
2016-10-21 12:19:34.023 Memory[67887:5677318] 0x6080000521e0
2016-10-21 12:19:34.023 Memory[67887:5677318] 0x608000260600
2016-10-21 12:19:34.023 Memory[67887:5677318] 0x6080002606c0

限制
歸檔和解檔的前提是NSArray中所有的對(duì)象都實(shí)現(xiàn)了NSCoding協(xié)議。

五晚胡、拾遺

1灵奖、關(guān)鍵字copy

代碼與結(jié)果

// 首先分別給出copy和strong修飾的屬性,以NSString舉例
// 1估盘、strong
@property (nonatomic, strong) NSString *str;
// 2瓷患、copy
@property (nonatomic, copy) NSString *str;

// 分別對(duì)1和2執(zhí)行下述代碼
NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"123"];
self.str = mutableStr;
[mutableStr appendString:@"456"];
NSLog(@"%@", self.str);
NSLog(@"%p", self.str);
NSLog(@"%@", mutableStr);
NSLog(@"%p", mutableStr);

// 結(jié)果1
2016-10-21 14:08:46.657 Memory[68242:5714288] 123456
2016-10-21 14:08:46.657 Memory[68242:5714288] 0x608000071040
2016-10-21 14:08:46.657 Memory[68242:5714288] 123456
2016-10-21 14:08:46.657 Memory[68242:5714288] 0x608000071040
// 結(jié)果2
2016-10-21 14:11:16.879 Memory[68264:5716282] 123
2016-10-21 14:11:16.880 Memory[68264:5716282] 0xa000000003332313
2016-10-21 14:11:16.880 Memory[68264:5716282] 123456
2016-10-21 14:11:16.880 Memory[68264:5716282] 0x60000007bbc0

分析

  • 結(jié)果1為strong修飾的結(jié)果,可見(jiàn)** [mutableStr appendString:@"456"]**修改mutableStr造成了self.str的改變遣妥,顯然不安全擅编;結(jié)果2為copy修飾的結(jié)果,可見(jiàn) [mutableStr appendString:@"456"]修改mutableStr未造成self.str的改變燥透,顯然安全沙咏。(從內(nèi)存地址的變化也可以看出來(lái))
  • 這里可以推測(cè)出辨图,copy關(guān)鍵字是在str屬性的set方法里面返回了mutableStr的copy班套,而strong關(guān)鍵字僅僅是返回了mutableStr。

2故河、深淺copy對(duì)引用計(jì)數(shù)的影響

淺copy吱韭,類(lèi)似strong,持有原始對(duì)象的指針鱼的,會(huì)使retainCount加一理盆。
深copy,會(huì)創(chuàng)建一個(gè)新的對(duì)象凑阶,不會(huì)對(duì)原始對(duì)象的retainCount變化猿规。

// 也許你會(huì)疑問(wèn)arc下如何訪問(wèn)retainCount屬性,這里提供了兩種方式(下面代碼中a代表一個(gè)任意對(duì)象宙橱,這個(gè)對(duì)象最好不要是NSString和NSNumber姨俩,因?yàn)橛盟鼈冞M(jìn)行測(cè)試會(huì)出問(wèn)題)
// kvc方式
NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)a));
// 橋接字方式
NSLog(@"Retain count %@", [a valueForKey:@"retainCount"]);

3、可變和不可變

可變和不可變上文談的不是很多师郑,因?yàn)楸疚恼J(rèn)為這完全與NSCopying和NSMutableCopying的實(shí)現(xiàn)息息相關(guān)环葵。當(dāng)然,對(duì)于框架類(lèi)宝冕,我們可以簡(jiǎn)單的認(rèn)為张遭,copy方法返回的就是不可變對(duì)象,mutableCopy返回的就是可變對(duì)象地梨。如果是自定義的類(lèi)菊卷,就看你怎么實(shí)現(xiàn)NSCopying和NSMutableCopying協(xié)議了缔恳。

4、copy和block

首先洁闰,MRR時(shí)代用retain修飾block會(huì)產(chǎn)生崩潰褐耳,因?yàn)樽鳛閷傩缘腷lock在初始化時(shí)是被存放在棧區(qū)或靜態(tài)區(qū)的,如果棧區(qū)的block內(nèi)調(diào)用外部變量渴庆,那么block無(wú)法保留其內(nèi)存铃芦,在初始化的作用域內(nèi)使用并不會(huì)有什么影響,但一旦出了block的初始化作用域襟雷,就會(huì)引起崩潰刃滓。所有MRC中使用copy修飾,將block拷貝到堆上耸弄。
其次咧虎,在ARC時(shí)代,因?yàn)锳RC自動(dòng)完成了對(duì)block的copy计呈,所以修飾block用copy和strong都無(wú)所謂砰诵。

5、strong和shallowCopy

這個(gè)問(wèn)題困惑了很久捌显,最后只能得出一個(gè)結(jié)論茁彭,淺copy和strong引用的區(qū)別僅僅是淺copy多執(zhí)行一步copyWithZone:方法。

六扶歪、文獻(xiàn)

1理肺、https://developer.apple.com/library/prerelease/content/documentation/Cocoa/Conceptual/Collections/Articles/Copying.html#//apple_ref/doc/uid/TP40010162-SW1
2、https://en.wikipedia.org/wiki/Object_copying

七善镰、感謝

最后妹萨,感謝來(lái)自百度的@楊飛宇同學(xué),和他的討論給了我很多靈感炫欺。也感謝大家的閱讀乎完,希望對(duì)您有所幫助。如果有錯(cuò)誤的地方或者不理解的地方品洛,希望大家在評(píng)論區(qū)積極指出树姨。如果對(duì)您有所幫助,希望給作者一個(gè)喜歡和關(guān)注毫别,您的支持是我最核心的動(dòng)力娃弓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市岛宦,隨后出現(xiàn)的幾起案子台丛,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挽霉,死亡現(xiàn)場(chǎng)離奇詭異防嗡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)侠坎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)蚁趁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人实胸,你說(shuō)我怎么就攤上這事他嫡。” “怎么了庐完?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵钢属,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我门躯,道長(zhǎng)淆党,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任讶凉,我火速辦了婚禮染乌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘懂讯。我一直安慰自己荷憋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布域醇。 她就那樣靜靜地躺著台谊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪譬挚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天酪呻,我揣著相機(jī)與錄音减宣,去河邊找鬼。 笑死玩荠,一個(gè)胖子當(dāng)著我的面吹牛漆腌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阶冈,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼闷尿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了女坑?” 一聲冷哼從身側(cè)響起填具,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后劳景,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體誉简,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年盟广,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闷串。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡筋量,死狀恐怖烹吵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情桨武,我是刑警寧澤年叮,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站玻募,受9級(jí)特大地震影響只损,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜七咧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一跃惫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艾栋,春花似錦爆存、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至悼粮,卻和暖如春癌椿,著一層夾襖步出監(jiān)牢的瞬間舔清,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留势木,地道東北人涡上。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓拦惋,卻偏偏與公主長(zhǎng)得像寻仗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昧穿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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