I have read the memory management guide from Apple and I don't see where this case is explained...
Many times, especially when writing a class method to return an instance of a class, I'll start it out like this, because that's how I've seen it done, and it works.
[NOTE] This code is from memory - I'll update it when I get home to show an example that really works (I made this up to illustrate it, but obviously I don't recall it well enough to construct something that makes sense...
[EDIT] Here's my actual method - of course everyone was right that I must be calling alloc
which I am.
+ (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;
}
So what I got from the responses is: * Declaring the instance just gets me a pointer to a memory location and tells Xcode what class the object will be. * Setting the pointer to nil pretty much just sets it to zero - keeping it from having garbage in it (right?) * Since I'm autoreleasing the instance, the object that is returned is also autoreleased.
Thanks for helping me understand this!
Can someone explain what the compiler does when it sees this?
DooDad* aDooDad = nil;
If you are really interested in what the compiler does, the answer is: the compiler will reserve some memory on the stack for the local variable aDooDad
, which is a pointer type (it is generally 64 or 32 bits in size depending on the processor). That pointer is then initialized to contain nil
(usually 0x00..00
).
A statement like this:
DooDad* aDooDad = [[DooDad alloc] init...];
makes use of pointer variable aDooDad
to store the address in memory of the object that is further allocated (which is the address of memory reserved by alloc
).
So, in the end,
DooDad* aDooDad = nil;
is not declaring an object, just a variable whose content is interpreted as the address of an object of DooDad
type. Such declaration, therefore, is just like any other declaration you know, e.g. when initializing an int
to 0, so that later you can assign it some value in an if
statement.
A statement like:
[aDooDad doSomething];
is interpreted by the Objective-C runtime system like: send message doSomething
to the object whose address is stored in aDooDad
. If that address is nil
no message is sent. On the other hand, if you dereference a nil pointer: *aDooDad
you'll get undefined behavior.
Pointers are pretty low level stuff. I hope this helps.
If you're familiar with C or C++, variables can be created in one of two ways, statically on the call stack, or dynamically on the heap. Variable memory created on the stack is is reclaimed when the current stack frame goes out of scope, so you never need to worry about creating or destroying it. In Objective-C, objects are always dynamically created. Primitives (like int, float, pointers, etc), can either be statically or dynamically created. For illustration:
- (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
}
So when you say DooDad* dodad = nil;
, you're creating a primitive (pointer to a DooDad) on the stack. Being a stack variable, you don't alloc or dealloc it, just like you wouldn't worry about alloc'ing or dealloc'ing any of the memory in the following method:
- (id)allStackVariables {
int myInt = 0;
float myFloat = 0.0f;
float* myFloatPtr = NULL;
NSObject* myObject = nil;
}
Setting it to nil
simply sets the contents of the variable to whatever the compiler defines to be nil
, something like 0x000000 in hex. Saying DooDad* dooDad = nil;
is conceptually identical to saying something like int myInt = 0;
Declaring simple gives you a pointer you can use later. No memory is allocated.
Not sure what the intent of the method you posted, but it seems wrong on many levels. It will return nil, always. Unless it's an initializer method, it should not call [self init]. If it is an initializer method, it should return self and be named something like "init..."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With