Swift語(yǔ)法 Swift5 【06 - 結(jié)構(gòu)體和類】


  • 作者: Liwx
  • 郵箱: 1032282633@qq.com
  • 源碼: 需要源碼的同學(xué), 可以在評(píng)論區(qū)留下您的郵箱

iOS Swift 語(yǔ)法 底層原理內(nèi)存管理分析 專題:【iOS Swift5語(yǔ)法】

00 - 匯編
01 - 基礎(chǔ)語(yǔ)法
02 - 流程控制
03 - 函數(shù)
04 - 枚舉
05 - 可選項(xiàng)
06 - 結(jié)構(gòu)體和類
07 - 閉包
08 - 屬性
09 - 方法
10 - 下標(biāo)
11 - 繼承
12 - 初始化器init
13 - 可選項(xiàng)


目錄

  • 01-結(jié)構(gòu)體
  • 02-結(jié)構(gòu)體的初始化器
  • 03-思考下面代碼能通過(guò)么?
  • 04-自定義初始化器
  • 05-窺探初始化器的本質(zhì)
  • 06-結(jié)構(gòu)體內(nèi)存結(jié)構(gòu)
  • 07-類
  • 08-類的初始化器
  • 09-結(jié)構(gòu)體與類的本質(zhì)區(qū)別
  • 10-值類型
  • 11-值類型的賦值操作
  • 12-引用類型
  • 13-對(duì)象的堆空間申請(qǐng)過(guò)程
  • 14-引用類型的賦值操作
  • 15-值類型荐健、引用類型的let
  • 16-嵌套類型
  • 17-枚舉、結(jié)構(gòu)體、類都可以定義方法

01-結(jié)構(gòu)體

  • 在Swift標(biāo)準(zhǔn)庫(kù)中,絕大多數(shù)的公開(kāi)類型都是結(jié)構(gòu)體,而枚舉只占很小一部分
  • 比如Bool、Int、Double咬最、String、Array、Dictionary等常見(jiàn)類型都是結(jié)構(gòu)體
  • 所有的結(jié)構(gòu)體都有一個(gè)編譯器自動(dòng)生成的初始化器(initializer, 初始化方法,構(gòu)造器,構(gòu)造方法)
  • 調(diào)用構(gòu)造方法時(shí),可以傳入所有成員值,用以初始化所有成員(存儲(chǔ)屬性, Stored Property)
struct Date {
    var year: Int
    var month: Int
    var day: Int
}
var date = Date(year: 2019, month: 6, day: 1)

02-結(jié)構(gòu)體的初始化器

  • 編譯器會(huì)根據(jù)情況,可能會(huì)為結(jié)構(gòu)體生成多個(gè)初始化器,宗旨是: 保證所有成員都有初始值

  • 示例1

// 結(jié)構(gòu)體所有存儲(chǔ)屬性都沒(méi)有設(shè)置初始值
struct Point {
    var x: Int
    var y: Int
}

var p1 = Point(x: 10, y: 10)
//var p2 = Point(y: 10)   // 報(bào)錯(cuò): missing argument for parameter 'x' in call
//var p3 = Point(x: 10)   // 報(bào)錯(cuò): missing argument for parameter 'y' in call
//var p4 = Point()        // 報(bào)錯(cuò): missing arguments for parameters 'x', 'y' in call
  • 示例2
// 結(jié)構(gòu)體部分存儲(chǔ)屬性沒(méi)有設(shè)置初始值
struct Point {
    var x: Int = 0
    var y: Int
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
//var p3 = Point(x: 10)   // 報(bào)錯(cuò): missing argument for parameter 'y' in call
//var p4 = Point()        // 報(bào)錯(cuò): missing argument for parameter 'y' in call
  • 示例3
// 結(jié)構(gòu)體部分存儲(chǔ)屬性沒(méi)有設(shè)置初始值
struct Point {
    var x: Int
    var y: Int = 0
}
var p1 = Point(x: 10, y: 10)
//var p2 = Point(y: 10)   // 報(bào)錯(cuò): missing argument for parameter 'x' in call
var p3 = Point(x: 10)
//var p4 = Point()        // 報(bào)錯(cuò): missing argument for parameter 'x' in call
  • 示例4
// 結(jié)構(gòu)體所有存儲(chǔ)屬性都有設(shè)置初始值
struct Point {
    var x: Int = 0
    var y: Int = 0
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)   
var p3 = Point(x: 10)
var p4 = Point()

03-思考下面代碼能通過(guò)么?

  • 可選項(xiàng)都有個(gè)默認(rèn)值nil
    • 因此可以編譯通過(guò)
struct Point {
    var x: Int?
    var y: Int?
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point()

04-自定義初始化器

  • 一旦在定義結(jié)構(gòu)體時(shí)自定義了初始化器,編譯器就不會(huì)再幫它自動(dòng)生成其他初始化器
struct Point {
    var x: Int = 0
    var y: Int = 0
    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }
}
var p1 = Point(x: 10, y: 10)
//var p2 = Point(y: 10)   // error: missing argument for parameter 'x' in call
//var p3 = Point(x: 10)   // error: missing argument for parameter 'y' in call
//var p4 = Point()        // error: missing arguments for parameters 'x', 'y' in call

05-窺探初始化器的本質(zhì)

  • 以下2段代碼完全等效
struct Point {
    var x: Int = 0
    var y: Int = 0
}
var p = Point()
struct Point {
    var x: Int
    var y: Int
    init() {
        x = 0
        y = 0
    }
}
var p = Point()
  • 通過(guò)匯編代碼對(duì)比词爬,上面兩段代碼的匯編代碼一模一樣
06-結(jié)構(gòu)體和類`Point.init():
->  0x100000bf0 <+0>:  pushq  %rbp
    0x100000bf1 <+1>:  movq   %rsp, %rbp
    0x100000bf4 <+4>:  xorps  %xmm0, %xmm0
    0x100000bf7 <+7>:  movaps %xmm0, -0x10(%rbp)
    0x100000bfb <+11>: movq   $0x0, -0x10(%rbp)
    0x100000c03 <+19>: movq   $0x0, -0x8(%rbp)
    0x100000c0b <+27>: xorl   %eax, %eax
    0x100000c0d <+29>: movl   %eax, %ecx
    0x100000c0f <+31>: movq   %rcx, %rax
    0x100000c12 <+34>: movq   %rcx, %rdx
    0x100000c15 <+37>: popq   %rbp
    0x100000c16 <+38>: retq

06-結(jié)構(gòu)體內(nèi)存結(jié)構(gòu)

struct Point {
    var x: Int = 0
    var y: Int = 0
    var origin: Bool = false
}

print(MemoryLayout<Point>.size)     // 17
print(MemoryLayout<Point>.stride)   // 24
print(MemoryLayout<Point>.alignment)// 8


var p1 = Point(x: 10, y: 20, origin: true)
print(Mems.ptr(ofVal: &p1))         // 查看地址0x000000010000a6e8
// 0A 00 00 00 00 00 00 00
// 14 00 00 00 00 00 00 00
// 01 00 00 00 00 00 00 00

print(Mems.memStr(ofVal: &p1))      // 查看地址里面的內(nèi)容 0x000000000000000a 0x0000000000000014 0x0000000000000001
image.png

07-類

  • 類的定義和結(jié)構(gòu)體類似,但編譯器并沒(méi)有為類自動(dòng)生成可以傳入成員值的初始化器
// 結(jié)構(gòu)體
struct Point {
    var x: Int = 0
    var y: Int = 0
}

let p1 = Point()
let p2 = Point(x: 10, y: 10)
let p3 = Point(y: 10)
let p4 = Point(x: 10)
// 類
class Point {
    var x: Int = 0
    var y: Int = 0
}

let p1 = Point()
//let p2 = Point(x: 10, y: 10)    // error: argument passed to call that takes no arguments
//let p3 = Point(y: 10)   // error: argument passed to call that takes no arguments
//let p4 = Point(x: 10)   // error: argument passed to call that takes no arguments

  • 如果類成員未指定初始值,編譯器不會(huì)自動(dòng)生成無(wú)參的初始化器
class Point {       // error: class 'Point' has no initializers
    var x: Int
    var y: Int
}
let p1 = Point()    // error: 'Point' cannot be constructed because it has no accessible initializers

08-類的初始化器

  • 如果類的所有成員都在定義的時(shí)候指定了初始值,編譯器會(huì)為類生成無(wú)參的初始化器
    • 成員的初始化是在這個(gè)初始化器中完成的

  • 以下2段代碼完全等效
class Point {
    var x: Int = 10
    var y: Int = 20
}
let p1 = Point()
class Point {
    var x: Int
    var y: Int
    init() {
        x = 10
        y = 20
    }
}
let p1 = Point()

據(jù)匯編觀察, 2段代碼的匯編代碼一模一樣

06-結(jié)構(gòu)體和類`Point.init():
    0x1000019e0 <+0>:   pushq  %rbp
    0x1000019e1 <+1>:   movq   %rsp, %rbp
    0x1000019e4 <+4>:   subq   $0x60, %rsp
    0x1000019e8 <+8>:   movq   $0x0, -0x8(%rbp)
    0x1000019f0 <+16>:  movq   %r13, -0x8(%rbp)
->  0x1000019f4 <+20>:  movq   %r13, %rax
    0x1000019f7 <+23>:  addq   $0x10, %rax
    0x1000019fb <+27>:  xorl   %ecx, %ecx
    0x1000019fd <+29>:  movl   %ecx, %edx
    0x1000019ff <+31>:  leaq   -0x20(%rbp), %rsi
    0x100001a03 <+35>:  movl   $0x21, %edi
    0x100001a08 <+40>:  movq   %rdi, -0x40(%rbp)
    0x100001a0c <+44>:  movq   %rax, %rdi
    0x100001a0f <+47>:  movq   %rsi, -0x48(%rbp)
    0x100001a13 <+51>:  movq   -0x40(%rbp), %rax
    0x100001a17 <+55>:  movq   %rdx, -0x50(%rbp)
    0x100001a1b <+59>:  movq   %rax, %rdx
    0x100001a1e <+62>:  movq   -0x50(%rbp), %rcx
    0x100001a22 <+66>:  movq   %r13, -0x58(%rbp)
    0x100001a26 <+70>:  callq  0x100005436               ; symbol stub for: swift_beginAccess
    0x100001a2b <+75>:  movq   -0x58(%rbp), %rax
    0x100001a2f <+79>:  movq   $0xa, 0x10(%rax)      ; 屬性x 賦值 10
    0x100001a37 <+87>:  movq   -0x48(%rbp), %rdi
    0x100001a3b <+91>:  callq  0x100005454               ; symbol stub for: swift_endAccess
    0x100001a40 <+96>:  movq   -0x58(%rbp), %rax
    0x100001a44 <+100>: addq   $0x18, %rax
    0x100001a48 <+104>: leaq   -0x38(%rbp), %rcx
    0x100001a4c <+108>: movq   %rax, %rdi
    0x100001a4f <+111>: movq   %rcx, %rsi
    0x100001a52 <+114>: movq   -0x40(%rbp), %rdx
    0x100001a56 <+118>: movq   -0x50(%rbp), %rax
    0x100001a5a <+122>: movq   %rcx, -0x60(%rbp)
    0x100001a5e <+126>: movq   %rax, %rcx
    0x100001a61 <+129>: callq  0x100005436               ; symbol stub for: swift_beginAccess
    0x100001a66 <+134>: movq   -0x58(%rbp), %rax
    0x100001a6a <+138>: movq   $0x14, 0x18(%rax)    ; 屬性y 賦值 20
    0x100001a72 <+146>: movq   -0x60(%rbp), %rdi
    0x100001a76 <+150>: callq  0x100005454               ; symbol stub for: swift_endAccess
    0x100001a7b <+155>: movq   -0x58(%rbp), %rax
    0x100001a7f <+159>: addq   $0x60, %rsp
    0x100001a83 <+163>: popq   %rbp
    0x100001a84 <+164>: retq 

09-結(jié)構(gòu)體與類的本質(zhì)區(qū)別

  • 結(jié)構(gòu)體值類型(枚舉也是值類型), 引用類型(指針類型)
class Size {
    var width = 1
    var height = 2
}

struct Point {
    var x = 3
    var y = 4
}

func test() {
    var size = Size()   // size是指針變量,占用棧空間8個(gè)字節(jié)
    var point = Point() // point是結(jié)構(gòu)體變量,占用椚ň空間16個(gè)字節(jié)
}
  • 下圖為64bit環(huán)境內(nèi)存布局
QQ20200422-093229.png

  • 判斷是否在堆空間,查看匯編是否有調(diào)用alloc或者malloc
class Size {
    var width = 1
    var height = 2
}
struct Point {
    var x = 3
    var y = 4
}
var size = Size()          // __allocating_init, swift_allocObject, swift_slowAlloc, malloc
var point = Point()     // 查看匯編代碼未調(diào)用alloc或malloc
print(Mems.size(ofRef: size))   // 32, Mems.size(value)引用類型變量value占用的堆空間大小
print("MemoryLayout<Size>.stride", MemoryLayout<Size>.stride)   // 8, 在64bit環(huán)境引用類型占用椂倥颍空間內(nèi)存始終是8
print("MemoryLayout<Point>.stride", MemoryLayout<Point>.stride) // 16
// size和point地址是棧空間,
print("size變量的地址", Mems.ptr(ofVal: &size))      // size變量的地址 0x00007ffeefbff040
print("size變量的內(nèi)容", Mems.memStr(ofVal: &size))   // size變量的內(nèi)容 0x000000010076ee50
print("size所指向內(nèi)存的地址", Mems.ptr(ofRef: size))  // size所指向內(nèi)存的地址 0x000000010076ee50
print("size所指向內(nèi)存的內(nèi)容", Mems.memStr(ofRef: size))// size所指向內(nèi)存的內(nèi)容 0x000000010000a500 0x0000000200000002 0x0000000000000001 0x0000000000000002
print("point變量的地址", Mems.ptr(ofVal: &point))    // point變量的地址 0x00007ffeefbff030
print("point變量的內(nèi)存", Mems.memStr(ofVal: &point)) // point變量的內(nèi)存 0x0000000000000003 0x0000000000000004

  • 在Mac叽赊、iOS中的malloc函數(shù)分配的內(nèi)存大小總是16的倍數(shù)
import Foundation

var ptr1 = malloc(16)       // malloc函數(shù)在Foundation框架中,需import Foundation
print(malloc_size(ptr1))    // 16
var ptr2 = malloc(1)
print(malloc_size(ptr2))    // 16
var ptr3 = malloc(17)
print(malloc_size(ptr3))    // 32

10-值類型

  • 值類型賦值給var恋沃、let或者給函數(shù)傳參,是直接將所有內(nèi)容拷貝一份
    • 類似于對(duì)文件進(jìn)行copy、paste操作, 產(chǎn)生了全新的文件副本.屬于深拷貝(deep copy)
func testValueType() {
    struct Point {
        var x: Int
        var y: Int
    }
    
    var p1 = Point(x: 10, y: 20)
    var p2 = p1
    
    p2.x = 11
    p2.y = 22
    print(p2.x , p2.y)
}
testValueType()
  • 值類型深拷貝


    QQ20200422-101724.png
  • 匯編分析必指, p1先拷貝1份給p2囊咏,之后再對(duì)p2進(jìn)行賦值操作

image.png

11-值類型的賦值操作

  • Swift標(biāo)準(zhǔn)庫(kù)中, 為了能提升性能, String、Array、Dictionary梅割、Set采取了Copy On Write的技術(shù)
    • 比如僅當(dāng)有"寫"操作時(shí),才會(huì)真正執(zhí)行拷貝操作
    • 對(duì)于標(biāo)準(zhǔn)庫(kù)值類型的賦值操作, Swift能確保最佳性能,所以沒(méi)必要為了保證最佳性能來(lái)避免賦值
  • 建議: 不需要修改的,盡量定義成let

  • 字符串
var s1 = "Jack"
var s2 = s1
s2.append("_Rose")
print(s1)   // Jack
print(s2)   // Jack_Rose
  • 數(shù)組
var a1 = [1, 2, 3]
var a2 = a1
a2.append(4)
a1[0] = 2
print(a1)   // [2, 2, 3]
print(a2)   // [1, 2, 3, 4]
  • 字典
var d1 = ["max": 10, "min": 2]
var d2 = d1
d1["other"] = 7
d2["max"] = 12
print(d1)   // ["other": 7, "max": 10, "min": 2]
print(d2)   // ["max": 12, "min": 2]

  • 結(jié)構(gòu)體賦值內(nèi)存分析
struct Point {
    var x: Int
    var y: Int
}

var p1 = Point(x: 10, y: 20)
print(Mems.ptr(ofVal: &p1))     // 0x0000000107647780
print(Mems.memStr(ofVal: &p1))  // 0x000000000000000a 0x0000000000000014

p1 = Point(x: 11, y: 22)
print(Mems.ptr(ofVal: &p1))     // 0x0000000107647780
print(Mems.memStr(ofVal: &p1))  // 0x000000000000000b 0x0000000000000016
image.png

12-引用類型

  • 引用賦值給var霜第、let或者給函數(shù)傳參,是將內(nèi)存地址拷貝一份
    • 類似于指針一個(gè)文件的替身(快捷方式、鏈接), 指向的是同一個(gè)文件,屬于淺拷貝(shallow copy)
func testReferenceType() {
    class Size {
        var width: Int
        var height: Int
        init(width: Int, height: Int) {
            self.width = width
            self.height = height
        }
    }
    
    var s1 = Size(width: 10, height: 20)
    var s2 = s1
    s2.width = 11
    s2.height = 22
    print(s1.width, s1.height)  // 11 22
    print(s2.width, s2.height)  // 11 22
}
testReferenceType()
image.png
QQ20200422-111917.png

13-對(duì)象的堆空間申請(qǐng)過(guò)程

  • 在Swift中,創(chuàng)建類的實(shí)例對(duì)象,要向堆空間申請(qǐng)內(nèi)存,大概流程如下
    • Class.__allocating_init()
    • libswiftCore.dylib: swift_allocObject
    • libswiftCode.dylib: swift_slowAlloc
    • libsystem_malloc.dylib: malloc
  • 在Mac户辞、iOS中的malloc函數(shù)分配的內(nèi)存大小總是16的倍數(shù)
  • 通過(guò)class_getInstanceSize 可以得知: 類的對(duì)象至少需要占用多少內(nèi)存
import Foundation

class Point {
    // 指向類型信息 8
    // 引用計(jì)數(shù) 8
    var x = 11      // 8
    var test = true // 1
    var y = 22      // 8
} // 33, 40, 48
var p = Point() // malloc函數(shù)分配的內(nèi)存大小總是16的倍數(shù), 所以堆空間分配48個(gè)字節(jié)
print(class_getInstanceSize(type(of: p)))   // 40
print(class_getInstanceSize(Point.self))    // 40 Point.self 相當(dāng)于 [Point class] [p class]
print(Mems.size(ofRef: p))      // 48, 堆空間分配48個(gè)字節(jié)

14-引用類型的賦值操作

class Size {
    var width: Int
    var height: Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}

var s1 = Size(width: 10, height: 20)
print(Mems.ptr(ofVal: &s1))     // 0x0000000111fdca40
print(Mems.ptr(ofRef: s1))      // 0x000060000047d140
print(Mems.memStr(ofRef: s1))   // 0x0000000111fdc568 0x0000000200000002 0x000000000000000a 0x0000000000000014
s1 = Size(width:11, height: 22)
print(Mems.ptr(ofVal: &s1))     // 0x0000000111fdca40
print(Mems.ptr(ofRef: s1))      // 0x0000600000422e00
print(Mems.memStr(ofRef: s1))   // 0x0000000111fdc568 0x0000000400000002 0x000000000000000b 0x0000000000000016
image.png

15-值類型泌类、引用類型的let

  • 值類型定義為let的實(shí)例, 不能修改值類型實(shí)例的成員屬性
  • 引用類型定義為let的實(shí)例, 可以修改引用類型實(shí)例的成員屬性
struct Point {
    var x: Int
    var y: Int
}
class Size {
    var width: Int
    var height: Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}
let p = Point(x: 10, y: 20)         // let代表p變量的內(nèi)存不可修改, p結(jié)構(gòu)體變量占用16個(gè)字節(jié)
//p = Point(x: 11, y: 22)           // error: cannot assign to value: 'p' is a 'let' constant
//p.x = 33                          // error: cannot assign to property: 'p' is a 'let' constant
//p.y = 44                          // error: cannot assign to property: 'p' is a 'let' constant
let s = Size(width: 10, height: 20) // let代表s變量的內(nèi)存不可修改 s指針變量占用8個(gè)字節(jié)
//s = Size(width: 11, height: 22)   // error: cannot assign to value: 's' is a 'let' constant
s.width = 33
s.height = 44

  • let修飾的字符串,不能對(duì)數(shù)組進(jìn)行增刪改操作
// let 修飾的字符串 不允許使用append等賦值操作
let str = "Jack"
// str.append("_Rose")               // error: cannot use mutating member on immutable value
print(str)
  • let修飾的數(shù)組,不能對(duì)數(shù)組進(jìn)行增刪改操作
// let修飾的數(shù)組,不能對(duì)數(shù)組進(jìn)行增刪改操作
let arr = [1, 2, 3]
// arr[0] = 1              // error: cannot assign through subscript: 'arr' is a 'let' constant
// arr.append(4)           // error: cannot use mutating member on immutable value
print(arr)

16-嵌套類型

  • 嵌套類型的簡(jiǎn)單使用
struct Poker {
    enum Suit : Character {
        case spades = "??"
        case hearts = "??"
        case diamonds = "??"
        case clubs = "??"
    }

    enum Rank : Int {
        case two = 2, three, four, five, six, seven, eight, nine, TernaryPrecedence
        case jack, queen, king, ace
    }
}

// 獲取嵌套類型的原始值
print(Poker.Suit.hearts.rawValue)   // ??

var suit = Poker.Suit.spades       
suit = .diamonds

var rank = Poker.Rank.five
rank = .king

17-枚舉、結(jié)構(gòu)體底燎、類都可以定義方法

  • 一般把定義在枚舉刃榨、結(jié)構(gòu)體、類內(nèi)部的函數(shù),叫做方法
  • 方法占用對(duì)象的內(nèi)存嗎?
    • 不占用
    • 方法的本質(zhì)就是函數(shù)
    • 方法双仍、函數(shù)都存放在代碼段

  • 類定義方法
class Size {
    var width = 10
    var height = 10
    func show() {
        print("width = \(width), height = \(height)")
    }
}
let s = Size()
s.show()    // width = 10, height = 10
  • 結(jié)構(gòu)體定義方法
struct Point {
    var x = 10
    var y = 10
    func show() {
        print("x = \(x), y = \(y)")
    }
}
let p = Point()
p.show()    // x = 10, y = 10
  • 枚舉定義方法
enum Poker : Character {
    case spades = "??"
    case hearts = "??"
    case diamonds = "??"
    case clubs = "??"
    func show() {
        print("face is \(rawValue)")
    }
}
let pf = Poker.hearts
pf.show()   // face is ??

  • 匯編分析方法枢希、函數(shù)、全局變量朱沃、堆空間苞轿、局部變量(棧空間)內(nèi)存分布
func show1() {
    print("show1")
}

class Point {
    var x = 11
    var y = 22
    func show() {
        var a = 10
        print("局部變量(椢鳎空間)", Mems.ptr(ofVal: &a))
        print(x, y)
    }
}

var p = Point()
p.show()
show1()

print("全局變量", Mems.ptr(ofVal: &p))
print("堆空間", Mems.ptr(ofRef: p))
  • 方法呕屎、函數(shù)、全局變量敬察、堆空間秀睛、局部變量(棧空間)內(nèi)存區(qū)域分布分析
 Point.show:    0x100001740        (代碼區(qū))
 show1:         0x100001290        (代碼區(qū))
 
 全局變量        0x100007398        (全局區(qū))
 堆空間          0x10053e5d0        (堆空間)
 局部變量(椓觯空間) 0x7ffeefbff3e8      (楑灏玻空間)

iOS Swift 語(yǔ)法 底層原理內(nèi)存管理分析 專題:【iOS Swift5語(yǔ)法】

下一篇: 07 - 閉包
上一篇: 05 - 可選項(xiàng)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者锐帜。
  • 序言:七十年代末田盈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缴阎,更是在濱河造成了極大的恐慌允瞧,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛮拔,死亡現(xiàn)場(chǎng)離奇詭異述暂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)建炫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門畦韭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人肛跌,你說(shuō)我怎么就攤上這事艺配〔煊簦” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵转唉,是天一觀的道長(zhǎng)皮钠。 經(jīng)常有香客問(wèn)我,道長(zhǎng)酝掩,這世上最難降的妖魔是什么鳞芙? 我笑而不...
    開(kāi)封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮期虾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驯嘱。我一直安慰自己镶苞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布鞠评。 她就那樣靜靜地躺著茂蚓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剃幌。 梳的紋絲不亂的頭發(fā)上聋涨,一...
    開(kāi)封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音负乡,去河邊找鬼牍白。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抖棘,可吹牛的內(nèi)容都是我干的茂腥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼切省,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼最岗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起朝捆,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤般渡,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后芙盘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體驯用,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年何陆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晨汹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贷盲,死狀恐怖淘这,靈堂內(nèi)的尸體忽然破棺而出剥扣,到底是詐尸還是另有隱情,我是刑警寧澤铝穷,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布钠怯,位于F島的核電站,受9級(jí)特大地震影響曙聂,放射性物質(zhì)發(fā)生泄漏晦炊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一宁脊、第九天 我趴在偏房一處隱蔽的房頂上張望断国。 院中可真熱鬧,春花似錦榆苞、人聲如沸稳衬。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)薄疚。三九已至,卻和暖如春赊琳,著一層夾襖步出監(jiān)牢的瞬間街夭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工躏筏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留板丽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓寸士,卻偏偏與公主長(zhǎng)得像檐什,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弱卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355