Управление объектами Objective-C с помощью c ++ std :: unique_ptr ‹› или std :: shared_ptr ‹›

Objective-C можно до некоторой степени смешивать с c ++, и можно вызывать друг друга. Но объекты Objective-C по-прежнему управляются более или менее вручную, а идиома RAII полностью отсутствует в языке. Интересно, можно ли управлять сроками жизни объектов Objective-C с помощью интеллектуальных указателей C ++. Особенно теперь, когда в стандарт C ++ 11 добавлены функции boost scoped_ptr и shared_ptr.


person diffeomorphism    schedule 22.12.2013    source источник
comment
Мои знания о C ++ намного меньше, чем о Objective-C, поэтому я могу понять ваш вопрос совершенно неправильно. Но зачем вам нужны интеллектуальные указатели C ++ для объектов Objective-C, если у вас есть ARC (автоматический подсчет ссылок)?   -  person Martin R    schedule 23.12.2013
comment
ARC требует явной отправки сообщений о выпуске. В C ++ эквивалентное сообщение декремента отправляется, когда локальная переменная экземпляра выходит за пределы области видимости (то есть функция, использующая ее, возвращает или выбрасывает)   -  person diffeomorphism    schedule 23.12.2013
comment
Но с ARC компилятор вставляет необходимые сообщения о сохранении / освобождении в скомпилированный код. Таким образом, с точки зрения программистов, объект автоматически освобождается, если он выходит за пределы области видимости.   -  person Martin R    schedule 23.12.2013


Ответы (1)


Но объекты Objective-C по-прежнему управляются более или менее вручную, а идиома RAII полностью отсутствует в языке.

Думаю, это так или иначе ответит на ваш вопрос. Поскольку объекты Objective-C подсчитываются по ссылкам, они уже выполняют цель, для которой были созданы интеллектуальные указатели: отделить или связать время жизни объекта с областью действия метода, в котором он содержится. scoped_ptrs можно воссоздать с помощью пулов автозапуска, а shared_ptrs - с помощью _3 _-_ 4_ или strong ссылок.

Но говорить «нет» - это скучно. Если вы действительно хотите смешать Objective-C и C ++ вот так, нам нужно сначала ослабить определение «объекта Objective-C». Среда выполнения распознает все, что isa является своим первым членом в качестве объекта, и мы можем воспользоваться этим и написать простой класс C ++ с соответствующим интерфейсом объекта, чтобы можно было отправлять сообщения:

@interface CFIObject : NSObject
- (void)doSomething;
@end

struct CFIObject_cxx {
    Class isa;
public:
    CFIObject_cxx() : isa([CFIObject class]) {}
~CFIObject_cxx() { printf("I'm dying!"); }
};

@implementation CFIObject
- (void)doSomething {
    NSLog("I did something.");
}
@end

Теперь мы можем создать экземпляр нашего объекта C ++ и обернуть его интеллектуальным указателем, который я намеренно разделю на два метода, чтобы проиллюстрировать время жизни объекта:

void func() {
    // Instantiate a smart pointer with our fake object.
    std::unique_ptr<CFIObject_cxx> cppObj (new CFIObject_cxx());
    id obj = (__bridge id)(cppObj.get());
    // The runtime thinks we're an object.
    [obj doSomething];
    // aaaand, it's out of scope.
}

int main(int argc, const char **argv) {
    func();
    return 0;
}

Как и следовало ожидать, это печатает:

2013-12-22 17:23:22.681 Test[77528:303] I did something
I'm dying!

к консоли.

В случае необходимости деструктор может быть оборудован для вызова -dealloc для имитации правильного разрушения объекта, но я надеюсь, вы видите, что все это совершенно не нужно, особенно с учетом того, что ARC становится умнее с каждым выпуском CLANG.

person CodaFi    schedule 23.12.2013