OC對(duì)象的本質(zhì)-isa指針 superclass指針詳解

特別備注

本系列文章總結(jié)自MJ老師在騰訊課堂開(kāi)設(shè)的OC底層原理課程便脊,相關(guān)圖片素材均取自課程中的課件。

面試題 – 面向?qū)ο?/h2>

對(duì)象的isa指針指向哪里隙券?

  • instance對(duì)象的isa指向class對(duì)象
  • class對(duì)象的isa指向meta-class對(duì)象
  • meta-class對(duì)象的isa指向基類的meta-class對(duì)象

OC的類信息存放在哪里?

  • 對(duì)象方法、屬性茁裙、成員變量弓乙、協(xié)議信息末融,存放在class對(duì)象中
  • 類方法,存放在meta-class對(duì)象中
  • 成員變量的具體值暇韧,存放在instance對(duì)象

isa指針

image-20210408102836107

OC對(duì)象分為三類

instance對(duì)象

  • 成員變量
  • 特殊的成員變量 isa指針

class對(duì)象勾习,用來(lái)描述instance對(duì)象

  • isa指針
  • superclass指針
  • 屬性信息
  • 對(duì)象方法信息(-方法)
  • 協(xié)議信息
  • instance對(duì)象的成員變量的描述信息

meta-class對(duì)象,用來(lái)存放類方法

  • isa指針
  • superclass指針
  • 類方法信息(+方法)
oc對(duì)象的分類以及內(nèi)部結(jié)構(gòu)

對(duì)一個(gè)類來(lái)說(shuō)懈玻,它的instance巧婶、classmete-class對(duì)象之間涂乌,一定是有某種聯(lián)系的艺栈。假設(shè)這種聯(lián)系不存在,我們看看會(huì)碰到什么問(wèn)題湾盒。比如我調(diào)用一個(gè)instance對(duì)象的方法

MJPerson *person = [[MJPerson alloc] init];
person->_age = 10;
[person personInstanceMethod];

它的底層是

通過(guò)xcrun編譯轉(zhuǎn)化成cpp文件

$ xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
image-20210408104259156
objc_msgSend([MJPerson class], @selector(personClassMethod))
objc_msgSend(instanceObj, @sel_registerName("instanceObjMethod"));

也就是給instanceObj對(duì)象發(fā)消息湿右。

instance對(duì)象不跟外界關(guān)聯(lián)的情況下,它內(nèi)部只有一些成員變量信息罚勾,是不可能完成方法調(diào)用的毅人,因?yàn)閷?duì)象方法是存放在class對(duì)象里面的吭狡,對(duì)class對(duì)象調(diào)用+方法的時(shí)候也是一樣,必須有辦法跟meta-class對(duì)象關(guān)聯(lián)起來(lái)堰塌,才能完成對(duì)+方法的調(diào)用赵刑。所以isa指針,就只它們之間的關(guān)聯(lián)场刑“愦耍可以通過(guò)下圖來(lái)理解isa的作用。

isa指針的作用

大致可以歸納為

  • instance對(duì)象isa指針指向class對(duì)象牵现。當(dāng)調(diào)用對(duì)象方法(-方法)時(shí)铐懊,通過(guò)instanceisa找到class,然后在class的方法列表里面找到對(duì)應(yīng)的實(shí)現(xiàn)進(jìn)行調(diào)用瞎疼。
  • class對(duì)象的isa指針指向meta-class對(duì)象科乎。當(dāng)調(diào)用類方法(+)方法時(shí),通過(guò)classisa找到meta-class贼急,最后在meta-class的方法列表找到對(duì)應(yīng)的實(shí)現(xiàn)進(jìn)行調(diào)用茅茂。

那么通過(guò)isa的橋接作用,我們應(yīng)該能更近一步地理解OC消息發(fā)送以及方法調(diào)用的過(guò)程了太抓。

superclass指針

image-20210408104554176

顯而易見(jiàn)空闲,從字面意思,我們就能知道走敌,superclass就是父類的意思碴倾。
假定我們有以下幾個(gè)類

// MJPerson
@interface MJPerson : NSObject <NSCopying>
{
    @public
    int _age;
}
@property (nonatomic, assign) int no;
- (void)personInstanceMethod;
+ (void)personClassMethod;
@end

// MJStudent
@interface MJStudent : MJPerson <NSCoding>
{
@public
    int _weight;
}
@property (nonatomic, assign) int height;
- (void)studentInstanceMethod;
+ (void)studentClassMethod;
@end

我們知道superclass指針存在于class對(duì)象meta-class對(duì)象里面。我們根據(jù)接下來(lái)的圖示來(lái)闡述一下:

class的superclass指針

一個(gè)類Studentclass對(duì)象里面的superclass指針指向該類的父類的class對(duì)象
當(dāng)Studentinstance對(duì)象要調(diào)用Person的對(duì)象方法時(shí)掉丽,會(huì)先通過(guò)isa找到Studentclass對(duì)象跌榔,然后通過(guò)這個(gè)class對(duì)象superclass找到Person(Student的父類)class對(duì)象,最后找到相應(yīng)的對(duì)象方法(-方法)的實(shí)現(xiàn)進(jìn)行調(diào)用

meta-class的superclass指針

一個(gè)類的meta-class里面的superclass指針指向該類的父類的meta-class對(duì)象

當(dāng)Studentclass對(duì)象要調(diào)用Person的類方法時(shí)捶障,會(huì)先通過(guò)isa找到Studentmeta-class對(duì)象僧须,然后通過(guò)這個(gè)meta-class對(duì)象superclass找到Person(Student的父類)meta-class對(duì)象,最后找到相應(yīng)的類方法(+方法)的實(shí)現(xiàn)進(jìn)行調(diào)用

isa残邀、superclass總結(jié)

image-20210408111637477
isa皆辽、superclass指針作用圖例

上圖完整描述了isa、superclass指針的作用芥挣,為了更加便于理解驱闷,我們?cè)诤竺娴膱D例中用Student代替subclass,Person代替superclass空免,NSObject代替Rootclass空另。

  • instanceisa指向class
  • classisa指向meta-class
  • meta-classisa指向基類的meta-class
  • classsuperclass指向父類的class如果沒(méi)有父類蹋砚,superclass指針為nil
  • meta-classsuperclass指向父類的meta-class,基類的meta-classsuperclass指向基類的class

instance調(diào)用對(duì)象方法的軌跡
我們以[student abc];為例扼菠,studentStudent類的實(shí)例對(duì)象,調(diào)用軌跡如下圖

img

對(duì)于student來(lái)說(shuō)摄杂,并不知道abc方法在哪里,唯一知道的就是可以去它的class對(duì)象里面找循榆,

  • 于是先通過(guò)isa指針進(jìn)入Student類的class對(duì)象析恢,如果在其中找到了abc就直接進(jìn)行調(diào)用,調(diào)用過(guò)程結(jié)束秧饮,
  • 沒(méi)找到的話映挂,就通過(guò)class對(duì)象superclass指針進(jìn)入Student類的父類,也就是Person類的class對(duì)象盗尸,重復(fù)上一步的查找邏輯
  • 以此類推柑船,一層一層往上尋找,如果最終到了基類泼各,也就是NSObject類的class對(duì)象里面鞍时,還沒(méi)找到的話,由于它的superclassnil扣蜻,最終就會(huì)碰到一個(gè)經(jīng)典的報(bào)錯(cuò)[ERROR: unrecognized selector sent to instance],調(diào)用軌跡結(jié)束

class調(diào)用類方法的軌跡
我們以[MJStudent abc];為例調(diào)用軌跡圖如下

img

對(duì)與Student類來(lái)說(shuō)逆巍,abc在哪也是不知道的,我們知道類方法被規(guī)定放在meta-class對(duì)象里面莽使,所以

  • 首先蒸苇,通過(guò)Studentclass對(duì)象isa指針找到其meta-class對(duì)象,然后在方法列表里面尋找是否有abc吮旅,有的話就調(diào)用,調(diào)用邏輯結(jié)束味咳。
  • 沒(méi)有的話庇勃,就通過(guò)meta-class對(duì)象superclass指針找到Student的父類Personmeta-class對(duì)象,然后查找abc方法槽驶,找到就調(diào)用责嚷,結(jié)束調(diào)用軌跡
  • 沒(méi)有的話,就通過(guò)Personmeta-class對(duì)象superclass指針掂铐,重復(fù)上一步的流程
  • 一次類推罕拂,通過(guò)meta-class對(duì)象superclass指針,一層層往上查找
  • 如果到了基類(NSObject)的meta-class還沒(méi)能夠找到abc全陨,此時(shí)比較特殊爆班,接下來(lái)的superclass指針會(huì)找到NSObject的class對(duì)象,你可能會(huì)奇怪辱姨,我們調(diào)用一個(gè)類方法柿菩,怎么跑到class對(duì)象里面來(lái)了,先保留你的疑問(wèn)雨涛,只需記住枢舶,蘋果確實(shí)是這么設(shè)計(jì)的懦胞,此時(shí)會(huì)繼續(xù)在NSObject的class對(duì)象里面,尋找abc凉泄,如果真的找到了abc躏尉,就會(huì)調(diào)用
    • 如果還沒(méi)有找到,由于此時(shí)的superclass是nil后众,最終系統(tǒng)將給出報(bào)錯(cuò)[ERROR: unrecognized selector sent to instance],調(diào)用軌跡結(jié)束
#import "NSObject+Test.h"

@implementation NSObject (Test)

+ (void)test
{
    NSLog(@"+[NSObject test] ++++++ %p", self);
}

- (void)test
{
    NSLog(@"-[NSObject test] -------- %p", self);
}
@end
@interface MJPerson : NSObject

+ (void)test;

@end

@implementation MJPerson

+ (void)test
{
    NSLog(@"+[MJPerson test] ++++++++ %p", self);
}

@end

測(cè)試instance調(diào)用對(duì)象方法的軌跡及class調(diào)用類方法的軌跡

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"[MJPerson class] - %p", [MJPerson class]);
        NSLog(@"[NSObject class] - %p", [NSObject class]);
        
        [MJPerson test];
        
        [NSObject test];
    }
    return 0;
}

輸出

2021-04-08 11:29:59.749350+0800 Interview02-isa和superclass[2891:125121] [MJPerson class] - 0x100004260
2021-04-08 11:29:59.749897+0800 Interview02-isa和superclass[2891:125121] [NSObject class] - 0x7fff8faa3118
2021-04-08 11:29:59.749951+0800 Interview02-isa和superclass[2891:125121] +[MJPerson test] ++++++++ 0x100004260
2021-04-08 11:29:59.749974+0800 Interview02-isa和superclass[2891:125121] +[NSObject test] ++++++ 0x7fff8faa3118
image-20210408113534660

當(dāng)我們把NSobject的test方法去掉

@implementation NSObject (Test)

- (void)test
{
    NSLog(@"-[NSObject test] -------- %p", self);
}
@end

此時(shí)調(diào)用軌跡右會(huì)發(fā)生神馬變化胀糜?

image-20210408114354345

isa指針指向哪里?

根據(jù)我們上面的梳理和總結(jié)吼具,我們可以得出結(jié)論

isa(of instance) --> isa(of class) --> isa(of meta-class)
下面我們通過(guò)代碼來(lái)驗(yàn)證一下

image-20210408112114296
// MJPerson
@interface MJPerson : NSObject <NSCopying>
{
@public
    int _age;
}
@property (nonatomic, assign) int no;
- (void)personInstanceMethod;
+ (void)personClassMethod;
@end

@implementation MJPerson

- (void)test
{
    
}

- (void)personInstanceMethod
{
    
}
+ (void)personClassMethod
{
    
}
- (id)copyWithZone:(NSZone *)zone
{
    return nil;
}
@end

// MJStudent
@interface MJStudent : MJPerson <NSCoding>
{
@public
    int _weight;
}
@property (nonatomic, assign) int height;
- (void)studentInstanceMethod;
+ (void)studentClassMethod;
@end

@implementation MJStudent
- (void)test
{
    
}
- (void)studentInstanceMethod
{
    
}
+ (void)studentClassMethod
{
    
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
    return nil;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    
}
@end
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MJPerson *person = [[MJPerson alloc] init];

        Class personClass = [MJPerson class];
        
        Class personMetaClass = object_getClass(personClass);
        NSLog(@"%p %p %p", person, personClass, personMetaClass);
    }
}

輸出

2021-04-08 11:52:08.970783+0800 Interview03-isa[3039:136373] 0x100415cf0 0x1000044c8 0x1000044a0

我們?cè)诖a中加入斷點(diǎn)僚纷,通過(guò)控制臺(tái)查看一下personisa信息。

image-20210408115845298

通過(guò)p/x命令來(lái)打印指針拗盒,/后面是打印參數(shù)怖竭,x參數(shù)表示用16進(jìn)制數(shù)輸出。因?yàn)槲覀冎?code>person這個(gè)instance的結(jié)構(gòu)體的包含一個(gè)isa成員變量陡蝇,person本身就是指針痊臭,所以可以通過(guò)person->isa訪問(wèn)isa的值。
代碼里面登夫,personClassPerson類class對(duì)象广匙,輸出結(jié)果顯示,

image-20210408120259351

person的isa = 0x001d8001000044c9
personClass = 0x00000001000044c8 它倆恼策。鸦致。。并不相等;量7滞佟! 這是什么情況狮斗?不是說(shuō)好了instance對(duì)象isa指向class`對(duì)象嘛绽乔?

其實(shí)在64位機(jī)器出現(xiàn)之前,instance對(duì)象isa確實(shí)是直接指向class對(duì)象的碳褒,
也就是
person->isa == personClass折砸,
從64bit開(kāi)始,isa需要進(jìn)行一次為運(yùn)算沙峻,才能計(jì)算出真實(shí)的class對(duì)象地址睦授,系統(tǒng)給我們提供了一個(gè)ISA_MASK,這個(gè)可以在objc4源碼里面找到。我先直接貼出來(lái)

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \
      uintptr_t nonpointer        : 1;                                       \
      uintptr_t has_assoc         : 1;                                       \
      uintptr_t has_cxx_dtor      : 1;                                       \
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
      uintptr_t magic             : 6;                                       \
      uintptr_t weakly_referenced : 1;                                       \
      uintptr_t deallocating      : 1;                                       \
      uintptr_t has_sidetable_rc  : 1;                                       \
      uintptr_t extra_rc          : 19
#   define RC_ONE   (1ULL<<45)
#   define RC_HALF  (1ULL<<18)

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating      : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)

# else
#   error unknown architecture for packed isa
# endif

大家請(qǐng)看清這里是分了arm64和x86_64的专酗,分別對(duì)應(yīng)的是移動(dòng)設(shè)備開(kāi)發(fā)和mac開(kāi)發(fā)睹逃。我的代碼是一個(gè)mac命令行工程,所以我們用x86的這個(gè)值來(lái)試一下

image-20210408120646325

可以看到,結(jié)果就顯而易見(jiàn)了沉填。通過(guò)和ISA_MASK進(jìn)行一次&運(yùn)算疗隶,我們得到了personClass的地址。同樣翼闹,我們來(lái)試一下personClass的isa指針斑鼻。

image-20210408120815969

結(jié)果我試圖通過(guò)personClass->isa先打印出其isa指針的時(shí)候,得到了錯(cuò)誤提示猎荠,告訴我們說(shuō)personClass的類型Class不是一個(gè)結(jié)構(gòu)體坚弱,看不太明白,那就先查看一下Class的定義关摇,typedef struct objc_class *Class;荒叶,然后在往下看一下objc_class的細(xì)節(jié)

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

雖然這個(gè)結(jié)構(gòu)體里面有isa指針,但是尾部的OBJC2_UNAVAILABLE;提示我們输虱,這已經(jīng)是過(guò)時(shí)的API了些楣。
不過(guò)我們知道class對(duì)象里面第一個(gè)成員變量確實(shí)是一個(gè)isa指針

struct mj_objc_class {
    Class isa;
};

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        MJPerson *person = [[MJPerson alloc] init];
        Class personClass = [MJPerson class];
        struct mj_objc_class *personClass2 = (__bridge struct cl_objc_class *)(personClass);
        Class personMetaClass = object_getClass(personClass);
        NSLog(@"%p %p %p", person, personClass, personMetaClass);
    }
    return 0;
}
image-20210408121705136

我們自定義一個(gè)struct,包含一個(gè)isa指針宪睹,然后再借助這個(gè)結(jié)構(gòu)體類型來(lái)讀取personClass里面的內(nèi)容愁茁,如上代碼,我們用personClass2在來(lái)嘗試一次

image-20210408121446943

ok亭病,結(jié)果顯示鹅很,class對(duì)象isa指針直接指向了mete-class對(duì)象的地址。

到此罪帖,上面的面試題相信大家已經(jīng)可以完整回答了促煮。在用一個(gè)圖來(lái)總結(jié)一下就是

image-20210408122032606

你會(huì)許還會(huì)問(wèn),那么superclass指針呢整袁,是不是也需要一個(gè)什么mask轉(zhuǎn)換污茵?答案是不需要的,可以用上面相同的方法進(jìn)行驗(yàn)證葬项。總之isa指針稍微特殊一點(diǎn)點(diǎn)迹蛤,特別記住一下關(guān)于ISA_MASK的細(xì)節(jié)就行民珍。

struct mj_objc_class {
    Class isa;
    Class superclass;
};
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // MJPerson類對(duì)象的地址:0x00000001000014c8
        // isa & ISA_MASK:0x00000001000014c8
        // MJPerson實(shí)例對(duì)象的isa:0x001d8001000014c9
        
        struct mj_objc_class *personClass = (__bridge struct mj_objc_class *)([MJPerson class]);

        struct mj_objc_class *studentClass = (__bridge struct mj_objc_class *)([MJStudent class]);

        NSLog(@"1111");
    }
}
image-20210408122944250
特別備注

本系列文章總結(jié)自MJ老師在騰訊課堂開(kāi)設(shè)的OC底層原理課程,相關(guān)圖片素材均取自課程中的課件盗飒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嚷量,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子逆趣,更是在濱河造成了極大的恐慌蝶溶,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抖所,居然都是意外死亡梨州,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門田轧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)暴匠,“玉大人,你說(shuō)我怎么就攤上這事傻粘∶拷眩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵弦悉,是天一觀的道長(zhǎng)窒典。 經(jīng)常有香客問(wèn)我,道長(zhǎng)稽莉,這世上最難降的妖魔是什么瀑志? 我笑而不...
    開(kāi)封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮肩祥,結(jié)果婚禮上后室,老公的妹妹穿的比我還像新娘。我一直安慰自己混狠,他們只是感情好岸霹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著将饺,像睡著了一般贡避。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上予弧,一...
    開(kāi)封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天刮吧,我揣著相機(jī)與錄音,去河邊找鬼掖蛤。 笑死杀捻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蚓庭。 我是一名探鬼主播致讥,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼器赞!你這毒婦竟也來(lái)了垢袱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后每强,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體笨奠,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡存和,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年肃晚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肮帐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牡直。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡救恨,死狀恐怖贸辈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肠槽,我是刑警寧澤擎淤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站秸仙,受9級(jí)特大地震影響嘴拢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寂纪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一席吴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捞蛋,春花似錦孝冒、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至搬设,卻和暖如春穴店,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拿穴。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工泣洞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人默色。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓球凰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親腿宰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弟蚀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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