Я вижу странное поведение, когда пытаюсь перехватить экземпляр класса C ++ в стеке в блоке Objective-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
будет захвачена блоком blk
, она будет иметь согласованное состояние. Однако это не так. Вывод этого кода следующий:
0x7fff5fbff650 default constructor
0x7fff5fbff630 copy constructor
about to call blk
0x7fff5fbff5d0 copy constructor
0x7fff5fbff5d0 destructor
flag=1 (test=0x7fff5fbff5d0)
0x7fff5fbff630 destructor
0x7fff5fbff650 destructor
Итак, локальный Test
экземпляр, который видит блок, получил свой деструктор! Все, что вы делаете с ним, является неопределенным поведением, которое очень вероятно приведет к сбою (например, если деструктор удалил указатель, не установив его в NULL).
Поддерживаются ли переменные экземпляра класса C ++ блоками Objective-C? Темы блочного программирования раздел "Объекты C ++", кажется, указывает, что они есть, но они явно не работают здесь. Это ошибка в компиляторе / среде выполнения? Это было проверено на GCC 4.2.1, Apple build 5666, на Mac OS X v10.6.8.