gpt4 book ai didi

ios - 在 Arc 中,Block 在什么情况下是 __NSMallocBlock__ 或 __NSStackBlock__ 或 __NSGlobalBlock__?

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:41:13 25 4
gpt4 key购买 nike

-(id)getBlockArray
{
int val = 10;

return [[NSArray alloc] initWithObjects:^{NSLog(@"1-%d",val);},^{NSLog(@"2-%d",val);} ,^{NSLog(@"3-");}, nil];
}

最佳答案

不捕获任何变量的 block 是全局 block 。由于 block 的所有实例都是相同的,编译器可以在程序的生命周期内静态分配一个副本。

捕获变量(闭包)的 block 是堆栈或堆(malloc) block 。 block 从堆栈开始,作为堆栈 block 。当第一次复制堆栈 block 时,它被移动到堆中。复制堆 block 不会创建另一个副本;但只是保留它。

第三个是全局 block 是显而易见的,因为它不捕获任何变量。前两个捕获变量。显然,第一个是复制的,第二个不是。

ARC 规范不保证前两个 block 中的任何一个都被复制。但是,如果需要,ARC 编译器可以插入额外的副本。 (复制一个 block 不会有什么坏处。)

我相信当前版本的 Clang ARC 编译器在将 block 指针类型的表达式传递给非 block 对象指针类型的参数时会保守地插入副本。这是一个好主意,因为采用非 block 对象指针的 API 通常只在需要存储它们时才保留它们,而不是在 block 需要时进行复制。事先复制它们可以防止这种情况下的不安全。这解释了第一个参数的复制。第二个呢?我的猜测是,这是因为它是可变参数而不是显式参数(-[NSArray initWithObjects:] 采用一个类型为 id 的参数,然后具有可变参数,.. .),而 Clang 关于传递时复制的规则可能不适用于可变参数(因为它不知道“参数类型”)。

在将 block 传递给采用普通对象指针并存储它们的 API 之前,您应该始终复制 block ,例如 -[NSArray initWithObjects:],因为无法保证复制。

关于ios - 在 Arc 中,Block 在什么情况下是 __NSMallocBlock__ 或 __NSStackBlock__ 或 __NSGlobalBlock__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29138936/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com