最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

iOS?block的值捕獲與指針捕獲詳解

 更新時(shí)間:2022年02月07日 16:38:16   作者:豌豆_射手  
Block它是C語(yǔ)言級(jí)別和運(yùn)行時(shí)方面的一個(gè)特征,下面這篇文章主要給大家介紹了關(guān)于iOS?block的值捕獲與指針捕獲的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

指針與指針變量

通俗的理解:

指針:內(nèi)存地址
指針變量:存放內(nèi)存地址的變量
指針變量的指針:指針變量自身的內(nèi)存地址

Person *p = [Person new]

右邊isa為:對(duì)象的內(nèi)存地址 - 指針

p為:指針變量

左邊isa為:指針變量的內(nèi)存地址 - 指針變量的指針

block捕獲變量方式

對(duì)局部變量捕獲有兩種形式:1、值捕獲(局部自動(dòng)變量) 2、指針捕獲(局部靜態(tài)變量);全局變量無(wú)需捕獲,可直接進(jìn)行訪問(wèn)。

clang -rewrite-objc **.m -o **.cpp 不同場(chǎng)景下轉(zhuǎn)換成C++代碼結(jié)果如下(嫌代碼長(zhǎng)不想看的直接看代碼下面的結(jié)論)

值捕獲

指針變量的捕獲

block內(nèi)部用一個(gè)新的指針變量來(lái)接收原指針變量。接收后,兩個(gè)指針變量里面存儲(chǔ)的值都是對(duì)象的內(nèi)存地址,所以也可以說(shuō)是值的捕獲。

局部自動(dòng)變量:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [Person new];
        void (^block)(void) = ^{
            NSLog(@"%@",p);
        };
        block();
    }
    return 0;
}
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  Person *p;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, Person *_p, int flags=0) : p(_p) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

  Person *p = __cself->p; // bound by copy
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_7w_wgxxl_655s9g6tms_7z44s6w0000gn_T_main_f76e59_mi_0,p);
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} 
__main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"));
        
        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, p, 570425344));
        
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

    }
    return 0;
}

代碼分析,生成的__main_block_impl_0結(jié)構(gòu)體里面創(chuàng)建了一個(gè)指針變量p,main函數(shù)里面的__main_block_impl_0初始化時(shí),傳入的也是指針變量p。所以block對(duì)局部自動(dòng)變量采用的捕獲方式是指針變量的捕獲,也就是值捕獲。

指針捕獲

對(duì)指針變量自身指針的捕獲

block內(nèi)部用一個(gè)新的指針來(lái)接收(指向)原指針變量自身的地址。

局部靜態(tài)變量:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        static Person *p = nil;
        p = [Person new];
        void (^block)(void) = ^{
            NSLog(@"%@",p);
        };
        block();
    }
    return 0;
}
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct __main_block_impl_0 {

  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  Person **p;
  
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, Person **_p, int flags=0) : p(_p) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

  Person **p = __cself->p; // bound by copy
  NSLog((NSString *)&__NSConstantStringImpl__var_folders_7w_wgxxl_655s9g6tms_7z44s6w0000gn_T_main_bd39c2_mi_0,(*p));
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __main_block_desc_0 {

  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);

  void (*dispose)(struct __main_block_impl_0*);

} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

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

    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;

        static Person *p = __null;
        p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"));

        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &p, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
    return 0;
}

代碼分析,生成的__main_block_impl_0結(jié)構(gòu)體里面創(chuàng)建了一個(gè)指針*p,main函數(shù)里面的__main_block_impl_0初始化時(shí),傳入的是指針變量p的地址&p。所以block對(duì)局部靜態(tài)變量采用的捕獲方式是指針變量自身地址的捕獲,也就是指針捕獲。

__block修飾的變量

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block Person *p = [Person new];
        void (^block)(void) = ^{
            NSLog(@"%@",p);
        };
        block();
    }
    return 0;
}
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct __Block_byref_p_0 {
  void *__isa;
__Block_byref_p_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 Person *p;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  
  __Block_byref_p_0 *p; // by ref
  
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_p_0 *_p, int flags=0) : p(_p->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_p_0 *p = __cself->p; // bound by ref
  NSLog((NSString *)&__NSConstantStringImpl__var_folders_7w_wgxxl_655s9g6tms_7z44s6w0000gn_T_main_6c171f_mi_0,(p->__forwarding->p));
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->p, (void*)src->p, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 8/*BLOCK_FIELD_IS_BYREF*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

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

    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        __attribute__((__blocks__(byref))) __Block_byref_p_0 p = {(void*)0,(__Block_byref_p_0 *)&p, 33554432, sizeof(__Block_byref_p_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"))};

        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_p_0 *)&p, 570425344));

        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

    }
    return 0;
}

代碼分析,使用__block修飾的指針變量p,會(huì)被轉(zhuǎn)換為_(kāi)_Block_byref_p_0的結(jié)構(gòu)體,結(jié)構(gòu)體內(nèi)持有p。main函數(shù)里面初始化__main_block_impl_0時(shí)傳入的是__Block_byref_p_0的地址,訪問(wèn)p時(shí),通過(guò)__Block_byref_p_0的__forwarding指針進(jìn)行訪問(wèn)。其實(shí)就相當(dāng)于block內(nèi)部捕獲了__Block_byref_p_0的指針,通過(guò)指針去訪問(wèn)__Block_byref_p_0持有的p。所以__block修飾的變量本質(zhì)上也相當(dāng)于是一種指針捕獲,只不過(guò)不是直接捕獲指針變量p的自身地址。

值捕獲能否重新賦值? 進(jìn)行值拷貝時(shí),block內(nèi)部同名指針變量如果執(zhí)行重新賦值操作,相當(dāng)于使內(nèi)部的指針變量指向了一個(gè)新的對(duì)象,再對(duì)此對(duì)象進(jìn)行任何操作都與原指針變量指向的原對(duì)象無(wú)關(guān),所以不能進(jìn)行重新賦值。

指針捕獲能否重新賦值? block內(nèi)部將block外部的指針變量的指針賦值給一個(gè)新的指針,block內(nèi)部、外部的指針都指向的是同一個(gè)指針變量。如果進(jìn)行賦值操作,操作的是同一個(gè)指針變量,所以可以進(jìn)行重新賦值。

關(guān)于block延伸的知識(shí)點(diǎn)

如果文章看到了這里,相信對(duì)值捕獲和指針捕獲已經(jīng)有了一個(gè)清晰的認(rèn)識(shí),那么可以自行思考以下幾個(gè)問(wèn)題,看是否真的理解了block,文章沒(méi)有的答案放在評(píng)論區(qū)

  • 值捕獲能否在block內(nèi)被重新賦值?如果是靜態(tài)變量呢?(文中已有)
  • 經(jīng)__block修飾變量生成的持有變量的結(jié)構(gòu)體里面__forwarding的意義在于什么?
  • 使用block有什么需要注意的點(diǎn),如何去解決?

總結(jié)

到此這篇關(guān)于iOS block的值捕獲與指針捕獲的文章就介紹到這了,更多相關(guān)iOS block值捕獲與指針捕獲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

乌兰浩特市| 沅陵县| 房产| 荃湾区| 绿春县| 横山县| 卓资县| 方山县| 阜南县| 中山市| 扶绥县| 大竹县| 宁陕县| 贵定县| 乌恰县| 渭源县| 富宁县| 内黄县| 分宜县| 东乌珠穆沁旗| 盐津县| 六枝特区| 梁平县| 阿荣旗| 简阳市| 西华县| 吉安县| 新闻| 阿勒泰市| 米泉市| 义乌市| 南京市| 乌兰县| 安阳市| 石泉县| 金乡县| 舒城县| 本溪| 濉溪县| 城市| 阿拉善左旗|