Objective C++块语义

Mar*_*ein 9 block objective-c objective-c++

考虑以下C++方法:

class Worker{
....
private Node *node
};

void Worker::Work()
{
    NSBlockOperation *op=[NSBlockOperation blockOperationWithBlock:  ^{
            Tool hammer(node);
            hammer.Use();
          }];
    ....
    }
Run Code Online (Sandbox Code Playgroud)

在捕获"节点"时,块确切地捕获了什么?对于其他情况,块的语言规范http://clang.llvm.org/docs/BlockLanguageSpec.html是明确的:

在复合语句范围内使用的变量以正常方式绑定到块,但自动(堆栈)存储中的变量除外.因此,可以按照人们的预期访问函数和全局变量,以及静态局部变量.[考验我]

块的复合语句中引用的本地自动(堆栈)变量将作为const副本导入并捕获.

但在这里,我们是否捕获了当前的这个值?副本这个使用工人的拷贝构造函数?或者对节点存储位置的引用?

特别是,假设我们说

 {
 Worker fred(someNode);
 fred.Work();
 }
Run Code Online (Sandbox Code Playgroud)

当块运行时,对象fred可能不再存在.节点的价值是多少?(假设底层的Node对象永远存在,但是工​​作者来去.)

相反,我们写了

void Worker::Work()
    {
        Node *myNode=node;
        NSBlockOperation *op=[NSBlockOperation blockOperationWithBlock:  ^{
                Tool hammer(myNode);
                hammer.Use();
              }];
        ....
        }
Run Code Online (Sandbox Code Playgroud)

结果有何不同?

ipm*_*mcc 10

根据这个页面:

通常,您可以在块中使用C++对象.在成员函数中,对成员变量和函数的引用是通过隐式导入的this指针,因此看起来是可变的.如果复制块,则有两个注意事项:

  • 如果你有一个基于堆栈的C++对象的__block存储类,那么使用通常的复制构造函数.
  • 如果在块中使用任何其他基于C++堆栈的对象,则它必须具有const复制构造函数.然后使用该构造函数复制C++对象.

根据经验,我观察到const将this指针复制到块中.如果this块执行时指向的C++实例不再位于该地址(例如,如果Worker::Work()调用的Worker实例在更高的帧上进行堆栈分配),那么您将获得EXC_BAD_ACCESS或更糟(即指针)混叠).所以看起来:

  • 它是捕获this,而不是按值复制实例变量.
  • 没有做任何事情来保持对象指向this活着.

或者,如果我引用本地堆栈分配(即在此堆栈帧/范围中声明)C++对象,我观察到它的复制构造函数在最初由块捕获时被调用,然后在复制块时再次被调用(对于例如,当您将操作排入队列时的操作队列.)

要具体解决您的问题:

但在这里,我们是否捕获了当前的价值this?使用Worker的拷贝构造函数的副本?或者对节点存储位置的引用?

我们捕获this.将它视为一个intptr_t如果有帮助的复制品.

fred当块运行时,该对象可能不再存在.有什么价值node?(假设底层的Node对象永远存在,但是工​​作者来去.)

在这种情况下,this已经通过值捕获并且node实际上是具有值的指针this + <offset of node in Worker>但是由于Worker实例消失了,所以它实际上是垃圾指针.

除了那些文档中描述的内容之外,我不会推断出任何魔法或其他行为.