我已经阅读了Apple的内存管理指南,我看不出这个案例的解释位置......
很多时候,特别是在编写类方法来返回类的实例时,我会像这样开始,因为这就是我看到它完成的方式,并且它有效。
[注意]这段代码来自内存 - 当我回到家时,我会更新它以显示一个真正有用的例子(我做了这个来说明它,但显然我不记得它构建一些东西这是有道理的......
[编辑]这是我的实际方法 - 当然每个人都应该打电话给我alloc
。
+ (id)player
{
Player *player = nil;
if ((player = [[[super alloc] initWithFile:@"rocket.png"] autorelease])) {
[player setProjectileType:kProjectileBullet];
[player setProjectileLevel:1];
[player setInvincible:YES];
[player setEmitter:[CCParticleSystemQuad particleWithFile:@"exhaust.plist"]];
[[player emitter] setPosition:ccp(0.0, player.contentSize.height/2)];
[player addChild:player.emitter];
}
return player;
}
所以我从回复中得到的是: *声明实例只是获取一个指向内存位置的指针,并告诉Xcode该对象将是什么类。 *将指针设置为nil几乎只是将其设置为零 - 防止其中有垃圾(对吗?) *由于我是自动释放实例,因此返回的对象也是自动释放的。
感谢您帮助我理解这一点!
答案 0 :(得分:11)
有人可以解释编译器在看到这个时会做什么吗?
DooDad* aDooDad = nil;
如果您真的对编译器的作用感兴趣,答案是:编译器将在堆栈上为局部变量aDooDad
保留一些内存,这是一种指针类型(通常为64位或32位)大小取决于处理器)。然后将该指针初始化为包含nil
(通常为0x00..00
)。
这样的陈述:
DooDad* aDooDad = [[DooDad alloc] init...];
利用指针变量aDooDad
将地址存储在进一步分配的对象的内存中(这是alloc
保留的内存地址)。
所以,最后,
DooDad* aDooDad = nil;
不是声明一个对象,只是一个变量,其内容被解释为DooDad
类型对象的地址。因此,这种声明就像你知道的任何其他声明一样,例如:将int
初始化为0时,以便稍后可以在if
语句中为其分配一些值。
如下的陈述:
[aDooDad doSomething];
由Objective-C运行时系统解释,如:将消息doSomething
发送到其地址存储在aDooDad
中的对象。如果该地址为nil
,则不会发送任何消息。另一方面,如果您取消引用一个零指针:*aDooDad
,您将获得未定义的行为。
指针是相当低级的东西。我希望这会有所帮助。
答案 1 :(得分:4)
如果你熟悉C或C ++,变量可以用两种方式之一创建,静态地在调用堆栈上创建,或者在堆上动态创建。当前堆栈帧超出范围时,将回收在堆栈上创建的可变内存,因此您无需担心创建或销毁它。在Objective-C中,对象始终动态创建。基元(如int,float,指针等)可以静态或动态创建。例如:
- (id)something {
NSObject myObject; // Illegal static object allocation
NSObject* myObject; // Legal primitive (pointer) static allocation
int myInt; // Legal primitive static allocation
int* myIntPtr; // Legal primitive (pointer) static allocation
}
所以当你说DooDad* dodad = nil;
时,你正在堆栈上创建一个原语(指向DooDad的指针)。作为堆栈变量,您不会分配或取消分配它,就像您不必担心在以下方法中分配或释放任何内存:
- (id)allStackVariables {
int myInt = 0;
float myFloat = 0.0f;
float* myFloatPtr = NULL;
NSObject* myObject = nil;
}
将其设置为nil
只需将变量的内容设置为编译器定义为nil
的内容,如十六进制中的0x000000。说DooDad* dooDad = nil;
在概念上与说int myInt = 0;
答案 2 :(得分:2)
声明simple会为您提供一个稍后可以使用的指针。没有分配内存。
不确定您发布的方法的意图,但在许多级别上似乎都是错误的。总是会返回零。除非它是初始化方法,否则不应该调用[self init]。如果它是初始化方法,它应该返回self并命名为“init ...”