Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 目标C在堆栈上分配对象_Objective C_Object_Stack - Fatal编程技术网

Objective c 目标C在堆栈上分配对象

Objective c 目标C在堆栈上分配对象,objective-c,object,stack,Objective C,Object,Stack,我对Objective C还不熟悉,并对对象进行了一些练习。而类似于Fraction*f=[[Fraction alloc]init]有效,每当我尝试做分数cI get无法静态分配接口类型堆栈上是否仍有分配对象的方法(如在c++中)?还是我尝试了错误的事情?您得到的错误是由于语法错误,您需要执行以下操作: Fraction *c; 请注意,缺少*表示这是指向对象的指针(您没有将此对象存储在堆栈上,您只是创建对(潜在)对象的引用)不,所有对象都在Obj-C中的堆上分配。您无法在目标C中静态分配

我对Objective C还不熟悉,并对对象进行了一些练习。而类似于
Fraction*f=[[Fraction alloc]init]有效,每当我尝试做
分数c
I get
无法静态分配接口类型
堆栈上是否仍有分配对象的方法(如在c++中)?还是我尝试了错误的事情?

您得到的错误是由于语法错误,您需要执行以下操作:

Fraction *c; 

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

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

您无法在目标C中静态分配对象。原因很多。包括应该初始化对象,但允许初始化方法更改对象的地址

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


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

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

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

从技术上讲,您可以(参见下面的代码),但不应该。此外,无论是在堆栈中还是在堆中,您只有一个指向对象的指针,而不是对象本身。也就是说,您应该编写
分数*c
,而不是
分数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;
    }
}
//在堆栈上分配Objective-C对象。
//格雷厄姆·李的原始代码:
// https://gist.github.com/iamleeg/5290797     
#进口
#包括
#包括
@接口A:NSObject
@财产(转让)含义;
@结束
@实施A
-(id)init{
if([super init]){
_意义=42;
}
回归自我;
}
@结束
int main(int argc,char*argv[]){
@自动释放池{
//分配和零堆栈内存
size_t size=class_getInstanceSize([A class]);
id obj=(uuu桥\传输id)alloca(大小);
memset((_桥空*)obj,0,大小);
//设置类并初始化对象
object_setClass(obj[A class]);
obj=[obj init];
NSLog(@“含义:%d”,[obj含义]);
//将所有权从ARC转移到CF,使ARC不会
//尝试不正确地释放堆栈分配的内存
CFTypeRef ref=(uu_桥_保留的CFTypeRef)obj;
}
}

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

除块对象外,所有objective-c对象都在堆中分配。主要原因是:

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

  • Mike Ash的一篇文章有助于理解这一点。

    您的代码中存在一个大问题。调用
    [obj init]
    可能会尝试取消分配对象并返回完全不同的对象。苹果不鼓励拆分alloc和init(
    Foo*bar=[Foo alloc];[bar init];
    ),因为在某些罕见的情况下init可能会改变对象分配,例如重新使用旧对象的内存(可能是UITableViewCell?)。但谁在乎呢,这只是一个在堆栈中分配对象的疯狂示例。:)在很多情况下,init可能会重新分配底层内存,甚至更多的情况下,init可能会释放底层内存并返回完全不同的内容。您甚至不能依赖于测试,因为这可能(实际上)会随着操作系统和库的版本而改变。这不仅仅是把它们分开的问题。更重要的是,
    init
    假设可以释放的内存与
    release
    autorelease
    一样多。