c++ - 堆栈上的 C++ 类实例可以被 Objective-C block 捕获吗?

标签 c++ objective-c objective-c++ objective-c-blocks

尝试在 Objective-C block 中的堆栈上捕获 C++ 类的实例时,我看到了一些奇怪的行为。考虑以下代码:

#import <Foundation/Foundation.h>
#include <stdio.h>

struct Test
{
  Test() : flag(0) { printf("%p default constructor\n", this); }
  Test(const Test& other) : flag(0) { printf("%p copy constructor\n", this); }
  ~Test() { flag = 1; printf("%p destructor\n", this); }

  int flag;
};

int main(int argc, char **argv)
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  Test test;
  void (^blk)(void) = ^(void)
    {
      printf("flag=%d (test=%p)\n", test.flag, &test);
    };
  printf("about to call blk\n");
  blk();

  [pool release];

  return 0;
}

人们会期望当局部变量test 被 block blk 捕获时,它具有一致的状态。然而,事实并非如此。此代码的输出如下:

0x7fff5fbff650 default constructor
0x7fff5fbff630 copy constructor
about to call blk
0x7fff5fbff5d0 copy constructor
0x7fff5fbff5d0 destructor
flag=1 (test=0x7fff5fbff5d0)
0x7fff5fbff630 destructor
0x7fff5fbff650 destructor

所以 block 看到的本地 Test 实例已经调用了它的析构函数!你用它做的任何事情都是未定义的行为,这很可能会导致崩溃(例如,如果析构函数删除了一个指针而没有将其设置为 NULL)。

Objective-C block 是否支持 C++ 类实例变量? Block Programming Topics “C++ 对象”部分似乎表明它们是,但它们显然不在这里工作。这是编译器/运行时中的错误吗?这是在 Mac OS X v10.6.8 上的 GCC 4.2.1、Apple build 5666 上测试的。

最佳答案

我会说它是 GCC 中的一个错误。

当我尝试使用 GCC 时,我得到:

0x7fff5fbff5d0 default constructor
0x7fff5fbff5c0 copy constructor
about to call blk
0x7fff5fbff570 copy constructor
0x7fff5fbff570 destructor
flag=1 (test=0x7fff5fbff570)
0x7fff5fbff5c0 destructor
0x7fff5fbff5d0 destructor

但是使用 LLVM 2.0:

0x7fff5fbff610 default constructor
0x7fff5fbff600 copy constructor
about to call blk
flag=0 (test=0x7fff5fbff600)
0x7fff5fbff600 destructor
0x7fff5fbff610 destructor

后者遵循我对 block 文档的解释(并且是唯一没有被公然破坏的版本)。

关于c++ - 堆栈上的 C++ 类实例可以被 Objective-C block 捕获吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7492026/

相关文章:

ios - 从文档文件夹中获取所有图像

c++ - 编译外部 C++ 库以用于 iOS 项目

cocoa - Objective-C++ 的支持程度如何?

iphone - Objective-C 中的字符串比较与类比较

c++ - 简化多个 ReadProcessMemory 调用

c# - 我如何将 C# string[] 编码(最好在 SWIG 中)到 C++ string*?

iphone - 保存没有质量损失的 UIImage

c++ - 逐行读取输入并转换为 vector 并打印

c++ - 在 UI 编辑器创建的按钮标题中使用 tr( )

ios - UITableView 部分中的背景图像隐藏部分标题