Objective c 目标C在堆栈上分配对象
我对Objective 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中静态分配
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
一样多。