块和堆栈 [英] Blocks and stack

查看:97
本文介绍了块和堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在堆栈中创建了块.但是,由于我对堆栈和局部变量没有足够的了解,因此我无法理解为什么我应该将块移到堆中才能获得预期的结果.凭直觉,我感觉到块代码块在堆栈中只有1个实例,此代码引用了局部变量i 3次.如果我将其复制到堆,它将具有3个不同的实例,并且每次复制过程中它将捕获3个不同的i值.但是我真的很想了解更多有关堆栈,堆和引用局部变量中的块代码的信息.

I know that blocks are created in the stack. However, since I don't have enough knowledge about stack and local variables, I can not understand why I should move the block to heap in order to have expected result. Intuitively I feel like the block code chunk has only 1 instance in the stack, this code is referencing to local variable i 3 times. If I copy it to heap it will have 3 different instances and each time it will capture 3 different values of i during copy procedure. But I would really like to know more about block code in stack, heap and referencing local variables.

for (int i=0; i<3; i++)
    b[i] = ^{ return i;};
for (int i=0; i<3; i++)
    printf("b %d\n", b[i]());

推荐答案

范围,伙计.范围.

将其重写为:

void georgeClinton() {
    int (^b[3])(); // iirc
    // georgeClinton's scope
    for (int i=0; i<3; i++) {
        // for's scope
        b[i] = ^{ return i;};
    }
}

在每次通过for()循环时,for的作用域实际上是一个新的作用域.但是,当然,范围在堆栈上.

On every pass through that for() loop, for's scope is effectively a new scope. But, of course, scopes are on the stack.

调用georgeClinton()时,可以有效地将georgeClinton()的作用域推入堆栈.而且当georgeClinton()返回时有些时髦时,georgeClinton()的作用域就会从堆栈中弹出 ,从而使堆栈处于推入发生时的任何状态(可能会修改返回值).

When you call georgeClinton(), you effectively push georgeClinton()'s scope onto the stack. And when georgeClinton() returns with some funky goodness, georgeClinton()'s scope is popped off the stack, leaving the stack in whatever state it was in when the push happened (with a potential modification for the return value).

for()循环是同一回事.每次迭代都会将状态压入堆栈,并在迭代结束时将其弹出.

A for() loop is the same thing; each iteration pushes state onto the stack and pops it off at the end of the iteration.

因此,如果您在for()循环的迭代中将任何内容存储在堆栈中(例如块),则该对象将在迭代结束时销毁.要保留它,必须将其移动到堆(在其中控制任何给定分配状态的寿命).

Thus, if you store anything on the stack in an iteration of a for() loop, like a block, that thing will be destroyed at the end of the iteration. To preserve it, you must move it to the heap (where you control the lifespan of the state of any given allocation).

关键是块类型变量实际上是一个指针;它是对定义块的结构的引用.它们从堆栈开始就是为了提高效率,这可能会导致像这样的细微问题.

The key being that a block typed variable is really a pointer; it is a reference to a structure that defines the block. They start on the stack for efficiency and this can lead to subtle issues like this one.

请注意,块实际上是两件事情;它是对实现该块的不可变代码的引用(实际上就像一个函数指针),并且它描述了在该块中捕获的数据以及如何处理该数据.复制后移到堆中.

Note that a block is really two things; it is a reference to the bit of immutable code that implements the block (which is really just like a function pointer) and it is a description of the data captured in the block and how that data is to be moved to the heap when copied.

也就是说,块是数据和代码的组合.永远不变的代码.作为执行指针捕获的数据将通过定义该块的表达式(即该块关闭"当前执行状态).

That is, a block is the combination of data and code. Code that never changes. Data that is captured as the execution pointer passes over the expression that defines the block (i.e. the block "closes over" the current state of execution).

后一点会让你绊倒;在堆栈上创建一个块时,会在其上创建插槽以容纳捕获的数据,同样在堆栈上.

It is that latter bit that trips you up; when a block is created on the stack, it is created with slots to hold captured data, also on the stack.

这篇关于块和堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆