Swift枚舉

C語(yǔ)言的枚舉

  • C語(yǔ)言的枚舉寫法
enum 枚舉名 { 
    枚舉值1,
    枚舉值2,
    ......
 };
  • 我們通過(guò)枚舉表示一周的七天
enum Week {
    MON,TUS,WED,THU,FRI,SAT,SUN
};
  • c語(yǔ)言中哎榴,枚舉的第一個(gè)成員默認(rèn)是為0嚷掠,后面的枚舉值一次類推地粪,也可以直接指定對(duì)應(yīng)的值,它后面的枚舉值依然是一次遞增
enum Week {
    MON=3,TUS,WED,THU=9,FRI,SAT,SUN
};
// 這個(gè)枚舉對(duì)應(yīng)的值就是3宰译,4檐蚜,5,9沿侈,10闯第,11,12

Swift的枚舉

Swift枚舉的使用

  • 同樣實(shí)現(xiàn)這個(gè)枚舉缀拭,其寫法如下
enum Week {
    case MON
    case TUS
    case WED
    case THU
    case FRI
    case SAT
    case SUN
}
// 也可以直接一個(gè)case乡括,用逗號(hào)隔開(kāi)
enum Week {
    case MON,TUS,WED,THU,FRI,SAT,SUN
}
  • 這樣表達(dá)的是一個(gè)整型的枚舉,和c語(yǔ)言的是一致的智厌,Swift中也可以用枚舉表達(dá)String
enum Week : String {
    case MON = "MON"
    case TUS = "TUS"
    case WED = "WED"
    case THU = "THU"
    case FRI = "FRI"
    case SAT = "SAT"
    case SUN = "SUN"
}
  • =右邊就是Swift中的RawValue诲泌,如果我們沒(méi)有寫后面的字符串,會(huì)默認(rèn)的隱式RawValue分配铣鹏,也可以對(duì)枚舉的成員單獨(dú)指定RawValue
  • 查看sil文件敷扫,可以看到自動(dòng)生成了一個(gè)init?(rawValue:)方法,和一個(gè)get方法
enum Week : String {
  case MON
  case TUS
  case WED
  case THU
  case FRI
  case SAT
  case SUN
  typealias RawValue = String
  init?(rawValue: String)
  var rawValue: String { get }
}
  • 我們來(lái)看下init?(rawValue:)函數(shù)是什么時(shí)候調(diào)用的,通過(guò)符號(hào)斷點(diǎn)來(lái)觀察
    image
  • 運(yùn)行發(fā)現(xiàn):Week.MON.rawValue并不會(huì)觸發(fā)init函數(shù)葵第,只有調(diào)用Week(rawValue: "MON")才會(huì)進(jìn)到符號(hào)斷點(diǎn)绘迁,再通過(guò)打印下面的代碼
print(Week(rawValue: "MON"))
print(Week(rawValue: "hello"))

// 打印結(jié)果  
Optional(SwiftEnumerate.Week.MON)
nil
  • 查看sil文件中init方法的實(shí)現(xiàn),首先我們會(huì)將枚舉值全部放到一個(gè)數(shù)組里面卒密,然后通過(guò)_findStringSwitchCase方法匹配傳入的字符串缀台,如果匹配到了就返回一個(gè)index,沒(méi)有匹配到就返回一個(gè)-1哮奇,再循環(huán)遍歷所有的枚舉值膛腐,匹配到了就取出對(duì)應(yīng)的枚舉值,然后包裝成一個(gè)可選項(xiàng)的值返回鼎俘,如果都沒(méi)有匹配到返回的就是nil哲身,所以返回值是一個(gè)可選項(xiàng)。
// Week.init(rawValue:)
sil hidden @$s4main4WeekO8rawValueACSgSS_tcfC : $@convention(method) (@owned String, @thin Week.Type) -> Optional<Week> {
// %0 "rawValue"                                  // users: %164, %158, %79, %3
// %1 "$metatype"
bb0(%0 : $String, %1 : $@thin Week.Type):
  %2 = alloc_stack $Week, var, name "self"        // users: %162, %154, %143, %132, %121, %110, %99, %88, %165, %159
  debug_value %0 : $String, let, name "rawValue", argno 1 // id: %3
  %4 = integer_literal $Builtin.Word, 7           // user: %6
  // function_ref _allocateUninitializedArray<A>(_:) 創(chuàng)建一個(gè)元組贸伐,里面有枚舉值數(shù)組勘天,和指針
  %5 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %6
  %6 = apply %5<StaticString>(%4) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // users: %8, %7
  %7 = tuple_extract %6 : $(Array<StaticString>, Builtin.RawPointer), 0 // users: %80, %79 
  %8 = tuple_extract %6 : $(Array<StaticString>, Builtin.RawPointer), 1 // user: %9
  %9 = pointer_to_address %8 : $Builtin.RawPointer to [strict] $*StaticString // users: %17, %69, %59, %49, %39, %29, %19
  %10 = string_literal utf8 "MON"                 // user: %12 創(chuàng)建一個(gè)字符串
  %11 = integer_literal $Builtin.Word, 3          // user: %16 它的長(zhǎng)度是3,我們?cè)趦?nèi)存中分配的大小
  %12 = builtin "ptrtoint_Word"(%10 : $Builtin.RawPointer) : $Builtin.Word // user: %16
  br bb1                                          // id: %13

bb1:                                              // Preds: bb0
  %14 = integer_literal $Builtin.Int8, 2          // user: %16
  br bb2                                          // id: %15

bb2:                                              // Preds: bb1
  %16 = struct $StaticString (%12 : $Builtin.Word, %11 : $Builtin.Word, %14 : $Builtin.Int8) // user: %17
  store %16 to %9 : $*StaticString                // id: %17
  %18 = integer_literal $Builtin.Word, 1          // user: %19
  %19 = index_addr %9 : $*StaticString, %18 : $Builtin.Word // user: %27 獲取當(dāng)前數(shù)組中的值的地址捉邢,返回相對(duì)于首地址的第(%18)個(gè)元素的地址
  %20 = string_literal utf8 "TUS"                 // user: %22
  %21 = integer_literal $Builtin.Word, 3          // user: %26
  %22 = builtin "ptrtoint_Word"(%20 : $Builtin.RawPointer) : $Builtin.Word // user: %26
  br bb3                                          // id: %23
  ......
bb14:                                             // Preds: bb13
  %76 = struct $StaticString (%72 : $Builtin.Word, %71 : $Builtin.Word, %74 : $Builtin.Int8) // user: %77
  store %76 to %69 : $*StaticString               // id: %77
  // function_ref _findStringSwitchCase(cases:string:)
  %78 = function_ref @$ss21_findStringSwitchCase5cases6stringSiSays06StaticB0VG_SStF : $@convention(thin) (@guaranteed Array<StaticString>, @guaranteed String) -> Int // user: %79 遍歷之前創(chuàng)建的數(shù)組匹配就返回對(duì)應(yīng)的index
  %79 = apply %78(%7, %0) : $@convention(thin) (@guaranteed Array<StaticString>, @guaranteed String) -> Int // users: %149, %138, %127, %116, %105, %94, %83, %147, %136, %125, %114, %103, %92, %81
  release_value %7 : $Array<StaticString>         // id: %80
  debug_value %79 : $Int, let, name "$match"      // id: %81
  %82 = integer_literal $Builtin.Int64, 0         // user: %84
  %83 = struct_extract %79 : $Int, #Int._value    // user: %84
  %84 = builtin "cmp_eq_Int64"(%82 : $Builtin.Int64, %83 : $Builtin.Int64) : $Builtin.Int1 // user: %85  循環(huán)比較當(dāng)前的返回值和index脯丝,根據(jù)結(jié)果往下跳轉(zhuǎn)不同的分支
  cond_br %84, bb15, bb16                         // id: %85
  
bb15:                                             // Preds: bb14
  %86 = metatype $@thin Week.Type
  %87 = enum $Week, #Week.MON!enumelt             // user: %89
  %88 = begin_access [modify] [static] %2 : $*Week // users: %89, %90
  store %87 to %88 : $*Week                       // id: %89
  end_access %88 : $*Week                         // id: %90
  br bb29                                         // id: %91
......
// 遍歷完全部枚舉值都沒(méi)有找到,就會(huì)返回一個(gè)none
bb28:                                             // Preds: bb26
  release_value %0 : $String                      // id: %158
  dealloc_stack %2 : $*Week                       // id: %159
  %160 = enum $Optional<Week>, #Optional.none!enumelt // user: %161
  br bb30(%160 : $Optional<Week>)                 // id: %161
// 匹配成功就創(chuàng)建一個(gè)可選項(xiàng)返回
bb29:                                             // Preds: bb27 bb25 bb23 bb21 bb19 bb17 bb15
  %162 = load %2 : $*Week                         // user: %163
  %163 = enum $Optional<Week>, #Optional.some!enumelt, %162 : $Week // user: %166
  release_value %0 : $String                      // id: %164
  dealloc_stack %2 : $*Week                       // id: %165
  br bb30(%163 : $Optional<Week>)                 // id: %166

// %167                                           // user: %168
bb30(%167 : $Optional<Week>):                     // Preds: bb29 bb28
  return %167 : $Optional<Week>                   // id: %168
} // end sil function '$s4main4WeekO8rawValueACSgSS_tcfC'
  • Swift源碼中_findStringSwitchCase的實(shí)現(xiàn)
/// The compiler intrinsic which is called to lookup a string in a table
/// of static string case values.
@_semantics("findStringSwitchCase")
public // COMPILER_INTRINSIC
func _findStringSwitchCase(
  cases: [StaticString],
  string: String) -> Int {

  for (idx, s) in cases.enumerated() {
    if String(_builtinStringLiteral: s.utf8Start._rawValue,
              utf8CodeUnitCount: s._utf8CodeUnitCount,
              isASCII: s.isASCII._value) == string {
      return idx
    }
  }
  return -1
}
  • 再看下它是如何獲取rawValue
// main 這里調(diào)用Week.rawValue.getter伏伐,返回一個(gè)字符串
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  alloc_global @$s4main1aSSvp                     // id: %2
  %3 = global_addr @$s4main1aSSvp : $*String      // user: %8
  %4 = metatype $@thin Week.Type
  %5 = enum $Week, #Week.MON!enumelt              // user: %7 創(chuàng)建一個(gè)枚舉值 MON
  // function_ref Week.rawValue.getter
  %6 = function_ref @$s4main4WeekO8rawValueSSvg : $@convention(method) (Week) -> @owned String // user: %7
  %7 = apply %6(%5) : $@convention(method) (Week) -> @owned String // user: %8
  store %7 to %3 : $*String                       // id: %8
  %9 = integer_literal $Builtin.Int32, 0          // user: %10
  %10 = struct $Int32 (%9 : $Builtin.Int32)       // user: %11
  return %10 : $Int32                             // id: %11
} // end sil function 'main'

// Week.rawValue.getter
sil hidden @$s4main4WeekO8rawValueSSvg : $@convention(method) (Week) -> @owned String {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $Week):
  debug_value %0 : $Week, let, name "self", argno 1 // id: %1
  switch_enum %0 : $Week, case #Week.MON!enumelt: bb1, case #Week.TUS!enumelt: bb2, case #Week.WED!enumelt: bb3, case #Week.THU!enumelt: bb4, case #Week.FRI!enumelt: bb5, case #Week.SAT!enumelt: bb6, case #Week.SUN!enumelt: bb7 // id: %2
// 匹配枚舉值巾钉,構(gòu)建字符串返回
bb1:                                              // Preds: bb0
  %3 = string_literal utf8 "MON"                  // user: %8
  %4 = integer_literal $Builtin.Word, 3           // user: %8
  %5 = integer_literal $Builtin.Int1, -1          // user: %8
  %6 = metatype $@thin String.Type                // user: %8
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %7 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %8
  %8 = apply %7(%3, %4, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %9
  br bb8(%8 : $String)                            // id: %9
  ...... //省略掉其他case的判斷,只判斷為MON的時(shí)候
// %52                                            // user: %53
bb8(%52 : $String):                               // Preds: bb7 bb6 bb5 bb4 bb3 bb2 bb1
  return %52 : $String                            // id: %53
} // end sil function '$s4main4WeekO8rawValueSSvg'
  • 這種情況下枚舉的值都是字符串常量秘案,存儲(chǔ)的位置應(yīng)該是在mach-o文件的__TEXT,__cstring,可以看到潦匈,當(dāng)前我們指定enumRawValueString之后阱高,系統(tǒng)自動(dòng)創(chuàng)建了一塊連續(xù)的內(nèi)存空間來(lái)默認(rèn)存放當(dāng)前case對(duì)應(yīng)的字符串。
    image

這里需要注意的一點(diǎn)就是枚舉值和RawValue是兩個(gè)不同的東?茬缩,我們沒(méi)有辦法把一個(gè)枚舉值分配一個(gè)String的變量赤惊,即使這個(gè)enumString類型的

關(guān)聯(lián)值

  • Swift中,我們可以通過(guò)枚舉值表達(dá)一個(gè)復(fù)雜的信息凰锡,就是關(guān)聯(lián)值未舟,通過(guò)枚舉來(lái)表達(dá)一個(gè)形狀,有圓形掂为,?方形裕膀,圓形有半徑,?方形有寬勇哗,高昼扛,這個(gè)時(shí)候關(guān)聯(lián)值就顯得非常有用了
enum Shape {
    case circle(radious:Double)
    case rectangle(width:Double,height:Double)
}
  • 我們使用了關(guān)聯(lián)值之后,就沒(méi)有RawValue欲诺,因?yàn)槲覀兠總€(gè)case都有一組值來(lái)表達(dá)抄谐,所以不需要使用RawValue渺鹦,這里我們使用的radiouswidth蛹含、height是我們自己取的標(biāo)簽毅厚,可以省略的
  • 創(chuàng)建一個(gè)關(guān)聯(lián)值的枚舉值
enum Shape {
    case circle(radious:Double)
    case rectangle(width:Double,height:Double)
    
}

var circle = Shape.circle(radious: 10.0)
var rectangle = Shape.rectangle(width: 15.0, height: 18.0)

枚舉的其他用法

模式匹配

  • 使用switch匹配枚舉值時(shí),需要遍歷所有可能的情況浦箱,不然編譯器會(huì)報(bào)錯(cuò)吸耿,如果不想匹配所有的case,可以使用defalut關(guān)鍵字代表默認(rèn)的情況憎茂。
    image
  • 關(guān)聯(lián)值的匹配
enum Shape {
    case circle(radious:Double)
    case rectangle(width:Double,height:Double)
    
}

var circle = Shape.circle(radious: 10.0)
var rectangle = Shape.rectangle(width: 15.0, height: 18.0)

switch circle {
    case let .circle(radious): print("circle radious\(radious)")
    case let .rectangle(width, height) : print("rectangle width:\(width),height:\(height)")
}
switch rectangle {
    case .circle(let radious): print("circle radious\(radious)")
    case .rectangle(let width,let height) : print("rectangle width:\(width),height:\(height)")
}
  • 匹配單個(gè)關(guān)聯(lián)值
if case let Shape.circle(radious) = circle {
    print(radious)
}
  • 不同的case的相同的關(guān)聯(lián)值
enum Shape{ 
    case circle(radious: Double, diameter: Double) 
    case rectangle(width: Double, height: Double) 
    case square(width: Double, width: Double) 
}
let shape = Shape.circle(radious: 10.0, diameter: 20.0) 
switch shape {
    case let .circle(x, 20.0), let .square(x, 20.0): 
        print(x) 
    default: 
        break 
} 
  • 使用通配符
switch shape {
    case let .circle(_, x), let .square(x, _):
        print(x) 
    default:
        break
}

switch shape {
    case let .circle(x, y), let .rectangle(y, x):
        print("x=\(x),y=\(y)") 
    default:
        break
}

枚舉的嵌套

  • 枚舉中嵌套枚舉
enum CombineDirect{
    enum BaseDirect{
        case up
        case down
        case left
        case right
    }

    case leftUp(combineElement1: BaseDirect, combineElement2: BaseDirect)
    case rightUp(combineElement1: BaseDirect, combineElement2: BaseDirect)
    case leftDown(combineElement1: BaseDirect, combineElement2: BaseDirect)
    case rightDown(combineElement1: BaseDirect, combineElement2: BaseDirect)
}

結(jié)構(gòu)體中的嵌套

  • 結(jié)構(gòu)體中嵌套枚舉
struct Skill {
    enum KeyType {
        case up
        case down
        case left
        case right
    }
    
    let key : KeyType
}

枚舉中包含屬性和方法

  • 枚舉中能夠包含計(jì)算屬性珍语,類型屬性,不能包含存儲(chǔ)屬性


    image
  • 枚舉中定義實(shí)例方法竖幔、static方法
enum Week : Int {
    case MON
    case TUS
    case WED
    case THU
    case FRI
    case SAT
    case SUN
    
    mutating func nextDay() {
        if self == .SUN {
            self = Week(rawValue: 1)!
        }else{
            self = Week(rawValue: 1+self.rawValue)!
        }
    }
    static func doSomething() {
        print("111\(self.init(rawValue: 1))")
    }
    
}

枚舉的大小

  • 一個(gè)case時(shí)候的大小
enum noMean {
    case a
}

print(MemoryLayout<noMean>.size)
print(MemoryLayout<noMean>.stride)

// 打印結(jié)果為:0 1
  • 普通的case沒(méi)有關(guān)聯(lián)值的時(shí)候板乙,枚舉的大小為一個(gè)字節(jié),一個(gè)字節(jié)所能表示的最大值為255拳氢,如果我們的case大于255的時(shí)候大小就會(huì)由Int8->Int16募逞,如果不夠就會(huì)繼續(xù)擴(kuò)大2倍
enum noMean {
    case a
    case b
}

print(MemoryLayout<noMean>.size)
print(MemoryLayout<noMean>.stride)

// 打印結(jié)果為:1 1

// 修改rawValue的類型 打印結(jié)果不變
enum noMean : String {
    case a
    case b
}
// 打印結(jié)果為:1 1
  • 有關(guān)聯(lián)值時(shí)候的枚舉的大小取決于最大的case內(nèi)存大小,但是大家看每次應(yīng)該是16馋评, 24放接, 32 這樣的偶數(shù),但是這里每次都是多加1留特,這里是不是就是我們當(dāng)前case的值啊纠脾,占用 1 字節(jié),只有一個(gè)case的時(shí)候蜕青,默認(rèn)size為0苟蹈。
enum Shape{
    case circle(radious: Double)
}
print(MemoryLayout<Shape>.size)
print(MemoryLayout<Shape>.stride)
// 打印結(jié)果為 8,8

enum Shape{
    case circle(radious: Double)
    case rectangle(width: Double, height: Double)
}
print(MemoryLayout<Shape>.size)
print(MemoryLayout<Shape>.stride)
// 打印結(jié)果為17右核,24
  • 打印內(nèi)存結(jié)構(gòu)


    image
需要注意的一點(diǎn)是慧脱,由于字節(jié)對(duì)齊的原因,有時(shí)候`case`的1字節(jié)會(huì)被編譯器優(yōu)化加到前面的位置上贺喝,它的大小不會(huì)再+1
  • 通過(guò)一段代碼來(lái)驗(yàn)證下剛剛的結(jié)論


    image
  • 修改circleradious的類型為Int
    image
  • 總結(jié)
    • 1菱鸥,RawValue的枚舉大小默認(rèn)是一字節(jié)(UInt8),也就意味著當(dāng)前最大能存儲(chǔ)的大小是 255躏鱼。如果超過(guò)這個(gè)大小氮采,當(dāng)前枚舉的大小就會(huì)從UInt8->UInt16依次類推
    • 2,關(guān)聯(lián)值的枚舉大小與最大的case的內(nèi)存大小相關(guān)染苛。

indirect關(guān)鍵字

  • 我們想通過(guò)枚舉實(shí)現(xiàn)一個(gè)鏈表扳抽,就需要使用indirect關(guān)鍵字
    image
  • 通過(guò)編譯器的修正后的寫法如下
indirect enum List<T> {
    case end
    case node(T, next : List<T>)
}
或
enum List<T> {
    case end
    indirect case node(T, next : List<T>)
}
  • 枚舉是值類型,也就意味著它的大小在編譯期就確定了,那么這個(gè)過(guò)程中對(duì)于我們當(dāng)前這個(gè)List的大小就不能確定贸呢,從系統(tǒng)的?度镰烧,我不知道當(dāng)前要給這個(gè)枚舉分配多大的內(nèi)存空間。所以怎么辦楞陷?官方文檔上有如下解釋

You indicate that an enumeration case is recursive by writing indi rect before it, which tells the compiler to insert the necessary l ayer of indirection.

  • 打印下它的大小


    image
  • 打印下實(shí)例對(duì)象的內(nèi)存結(jié)構(gòu)


    image
  • 查看sil文件怔鳖,alloc_box的本質(zhì)就是調(diào)用swift_allocObjet,所以indirect關(guān)鍵字其實(shí)就是通知編譯器固蛾,我當(dāng)前的枚舉是遞歸的结执,自然而然大小也就不確定,所以趕緊給我分配一塊堆區(qū)的內(nèi)存空間存放艾凯。
    image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末献幔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子趾诗,更是在濱河造成了極大的恐慌蜡感,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恃泪,死亡現(xiàn)場(chǎng)離奇詭異郑兴,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贝乎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門情连,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事《庀ィ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵挽拔,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我衡招,道長(zhǎng),這世上最難降的妖魔是什么每强? 我笑而不...
    開(kāi)封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任始腾,我火速辦了婚禮,結(jié)果婚禮上空执,老公的妹妹穿的比我還像新娘浪箭。我一直安慰自己,他們只是感情好辨绊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布奶栖。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宣鄙。 梳的紋絲不亂的頭發(fā)上袍镀,一...
    開(kāi)封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音冻晤,去河邊找鬼苇羡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鼻弧,可吹牛的內(nèi)容都是我干的设江。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼攘轩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼叉存!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起度帮,我...
    開(kāi)封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤歼捏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后够傍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體甫菠,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年冕屯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了寂诱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡安聘,死狀恐怖痰洒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浴韭,我是刑警寧澤丘喻,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站念颈,受9級(jí)特大地震影響泉粉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜榴芳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一嗡靡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窟感,春花似錦讨彼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)哩至。三九已至,卻和暖如春蜜自,著一層夾襖步出監(jiān)牢的瞬間菩貌,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工袁辈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菜谣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓晚缩,卻偏偏與公主長(zhǎng)得像尾膊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荞彼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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