Объекты в Objective-C когда-либо создавались в стеке?

Насколько я понимаю, в C++ можно создавать объекты в стеке:

SomeClass object = SomeClass();

или в куче:

SomeClass *object = new SomeClass();

В Objective-C кажется, что вы всегда создаете объекты в куче, поскольку [SomeClass alloc] возвращает указатель на новый экземпляр. Это правильно?

Объекты когда-либо размещались в стеке? Если да, то что может быть хорошим примером? Иначе почему бы и нет?


person Jawap    schedule 18.12.2013    source источник
comment
Как насчет int x = 0; ?(Цель C)   -  person Roma-MT    schedule 18.12.2013


Ответы (2)


Короткий ответ: объекты всегда размещаются в куче, а не в стеке.

Хотя это далеко не вся история. В Objective-C блоки также являются полноценными объектами Objective-C. Они отличаются тем, что иногда находятся в стеке. В частности, блоки, созданные с синтаксисом блочного литерала и ссылающиеся на окружающую область, находятся в стеке. Вы даже можете увидеть это, если проверите их класс, который будет (приватным) NSStackBlock. Если вы скопируете их с помощью Block_copy() или -copy, результирующая копия будет в куче (NSMallocBlock).

Одним из следствий этого является то, что блоки, размещенные в стеке, действительны только до конца области, в которой они были созданы. До ARC (а также IIRC в ранней версии ARC) это означало, что вам приходилось копировать блоки, которые вы хотели использовать, за пределы их области создания, чтобы они были в куче. ARC обрабатывает это за вас в большинстве случаев, а также означает, что труднее предсказать, находится ли блок в стеке или в куче.

Эта небольшая тестовая программа показывает это (компилировать с выключенным ARC):

#import <Foundation/Foundation.h>

// Compile this without ARC.

int main(int argc, char *argv[]) {
    @autoreleasepool {

        NSMutableString *string = [NSMutableString stringWithString:@"foo"];
        void(^stackBlock)() = ^{
            [string setString:@"bar"];
        };
        NSLog(@"stackBlock class: %@", NSStringFromClass([stackBlock class]));

        void(^heapBlock)() = [[stackBlock copy] autorelease];
        NSLog(@"heapBlock class: %@", NSStringFromClass([heapBlock class]));
    }
}

Выход:

stackBlock class: __NSStackBlock__
heapBlock class: __NSMallocBlock__

(Просто для ясности: вам определенно не следует использовать проверку NSStackBlock/NSMallocBlock в реальном коде. Это частные классы деталей реализации. Этот код предназначен только для демонстрации.)

person Andrew Madsen    schedule 18.12.2013

Базовые примитивные типы (int, float и double) будут созданы в стеке.

Фактический указатель (то есть object в SomeClass* object) создается в стеке, даже если он указывает на объект в куче.

Вы правы, говоря, что все, что создано с помощью new, создается в куче.

person Bathsheba    schedule 18.12.2013
comment
Я знаю о примитивах и указателях. Но реальные объекты никогда не помещаются в стек, т.е. вы не могли бы сделать это, даже если бы захотели? - person Jawap; 18.12.2013
comment
Нет, так как все объекты создаются с помощью new. - person Bathsheba; 18.12.2013
comment
Что вы имеете в виду, когда все объекты создаются с помощью new? В Objective-C? Вы имеете в виду alloc? Насколько известно, new в Objective-C — это просто ярлык для alloc/init. - person Jawap; 18.12.2013