4

我是 Objective C 的新手,并且对对象进行了一些练习。虽然类似的东西可以Fraction* f = [[Fraction alloc] init ];工作,但每当我尝试这样做时,Fraction c;我会得到Interface type cannot be statically allocated是否有在堆栈上分配对象(如在 c++ 中)?还是我在尝试错误的事情?

4

6 回答 6

4

您不能在 Objective C 中静态分配对象。这有很多原因。包括应该初始化对象但允许初始化方法更改对象地址的事实。

在 C++ 中,构造函数必须初始化它所调用的对象,并且不能以任何方式更改对象地址。这在 Objective C 中是不正确的。构造函数的等价物(alloc+init* 序列或类级别的方法)被允许决定它们将要更改它们被调用的对象的地址(它们将处理当然,释放原始对象)。

当然,他们无法释放静态分配的内存,也无法更改堆栈的地址。

于 2012-09-14T11:35:52.723 回答
3

从技术上讲,你可以(见下面的代码),但你不应该。此外,无论是在堆栈中还是在堆中,您只有一个指向对象的指针,而不是对象本身。也就是说,你应该写Fraction *c,而不是Fraction c

// Allocate an Objective-C object on the stack.
// Original code By Graham Lee: 
// https://gist.github.com/iamleeg/5290797     

#import <Foundation/Foundation.h>
#include <stdlib.h>
#include <objc/runtime.h>

@interface A : NSObject
@property (assign) int meaning;
@end

@implementation A

- (id)init {
    if ([super init]) {
        _meaning = 42;
    }
    return self;
}

@end


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

        // allocate and zero stack memory
        size_t size = class_getInstanceSize([A class]);
        id obj = (__bridge_transfer id) alloca(size);
        memset((__bridge void*)obj, 0, size);

        // set class and initialize the object
        object_setClass(obj, [A class]);
        obj = [obj init];

        NSLog(@"meaning: %d", [obj meaning]);

        // transfer ownership from ARC to CF so ARC doesn't 
        // try to improperly free the stack allocated memory
        CFTypeRef ref = (__bridge_retained CFTypeRef) obj;
    }
}

alloca()是非标准的,不安全的,不可移植的,并且容易发生堆栈溢出。

于 2013-04-03T08:18:33.267 回答
1

不,所有对象都分配在 Obj-C 的堆上。

于 2012-09-14T11:35:32.970 回答
1

不,您不能将堆栈用于 Objective-C 对象的内存,它必须是堆(通过allocinit)。

虽然正如@wattson12 所指出的,您显然可以将对象引用(指针)存储在堆栈上,但这仍然不会将堆栈用于对象的内存。

于 2012-09-14T11:36:06.900 回答
0

您收到的错误是由于语法错误,您需要这样做:

Fraction *c; 

请注意缺少的 * 表示这是一个指向对象的指针(您没有将此对象存储在堆栈中,您只是在创建对(潜在)对象的引用)

于 2012-09-14T11:33:26.230 回答
0

除块对象外,所有objective-c 对象都分配在堆中。造成这种情况的主要原因是:

  1. 在 Objective-C 中不跟踪指向对象的指针(相反,Objective-C 使用引用计数系统进行内存管理);如果您移动对象,它们将无法更新。
  2. 当创建它们的函数返回时,堆栈对象将被销毁。

Mike Ash的帖子有助于理解这一点。

于 2015-07-15T06:22:42.197 回答