2011-06-10 12 views
8

He leído la guía de gestión de memoria de Apple y no veo dónde se explica este caso ...¿Qué hace Objective-C en realidad cuando declaras un objeto?

Muchas veces, especialmente cuando escribo un método de clase para devolver una instancia de una clase, comenzaré de esta manera, porque así es como lo he visto y funciona.

[NOTA] Este código es de memoria - Lo actualizaré cuando llegue a casa para mostrar un ejemplo que realmente funciona (lo hice para ilustrarlo, pero obviamente no lo recuerdo lo suficientemente bien como para construirlo . algo que tiene sentido ...

[EDIT] Aquí está mi método actual - por supuesto, todo el mundo era correcto que debo estar llamando alloc que estoy

+ (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; 
} 

Así que lo que obtuve de las respuestas es: * Declarar la instancia solo me da un puntero a una ubicación de memoria y le dice a Xcode qué clase será el objeto. * Ajuste del puntero a cero prácticamente sólo lo pone a cero - evitando que tener la basura en ella (? Derecha) * Ya que estoy autoreleasing la instancia, el objeto que se devuelve es también autoreleased.

Gracias por ayudarme a entender esto!

+4

¿Dónde ha visto lo anterior "hecho?" El código que ha enumerado aquí no tiene sentido, y no espero que funcione. –

+0

@Rob - ver mi edición arriba; Voy a editar con el código actual esta noche. Gracias por ser paciente. – Steve

Respuesta

11

¿Alguien puede explicar qué hace el compilador cuando lo ve?

DooDad* aDooDad = nil; 

Si usted está realmente interesado en lo que hace el compilador, la respuesta es: el compilador reservar algo de memoria en la pila de la variable local aDooDad, que es un tipo de puntero (por lo general 64 o 32 bits de tamaño dependiendo del procesador). Ese puntero se inicializa para contener nil (generalmente 0x00..00).

Una declaración como esta:

  DooDad* aDooDad = [[DooDad alloc] init...]; 

hace uso de la variable de puntero aDooDad para almacenar la dirección en memoria del objeto que se asigna más (que es la dirección de memoria reservada por alloc).

Así que, al final,

DooDad* aDooDad = nil; 

es no declarar un objeto, sólo una variable cuyo contenido se interpreta como la dirección de un objeto de tipo DooDad. Dicha declaración, por lo tanto, es como cualquier otra declaración que conozca, p. al inicializar int en 0, para que luego pueda asignarle algún valor en una declaración if.

Una declaración como:

[aDooDad doSomething]; 

es interpretado por el sistema de ejecución de Objective-C como: enviar mensaje doSomething al objeto cuya dirección está almacenada en aDooDad. Si esa dirección es nil, no se envía ningún mensaje. Por otro lado, si desreferencia un puntero nulo: *aDooDad obtendrá un comportamiento indefinido.

Los apuntadores son cosas de muy bajo nivel. Espero que esto ayude.

2

Declarar simple que da un puntero se puede utilizar más adelante. No se asigna memoria.

No está seguro de cuál es la intención del método informados, pero parece mal en muchos niveles. Devolverá nil, siempre. A menos que sea un método de inicialización, no debe llamar a [self init]. Si se trata de un método de inicialización, debería devolverlo y llamarse como "init ..."

+0

lo siento, estoy escribiendo esto de memoria. No estoy seguro del código exacto a excepción de la parte de declaración del puntero. Sé que no estoy llamando 'alloc ', sino simplemente' init'. Es parte de un proyecto 'cocos2d' y mi clase real es una subclase de' CCSprite, 'y el método' init' es 'initWithFile:' – Steve

+1

@Steve: llamar a 'init' en un valor' nil' es una operación no operativa y ciertamente no hará nada útil. – geoffspear

4

Si está familiarizado con C o C++, las variables se pueden crear de una de dos formas, estáticamente en la pila de llamadas o dinámicamente en el montón. La memoria variable creada en la pila se recupera cuando el marco de pila actual queda fuera del alcance, por lo que nunca tendrá que preocuparse por crearlo o destruirlo. En Objective-C, los objetos son siempre creados dinámicamente. Los primitivos (como int, float, punteros, etc.) pueden crearse estática o dinámicamente. A título de ejemplo:

- (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 
} 

Así, cuando decimos DooDad* dodad = nil;, que está creando una primitiva (puntero a una Doodad) en la pila. Al ser una variable de pila, no lo hace alloc o dealloc que, al igual que usted no se preocupe por alloc'ing o dealloc'ing cualquiera de la memoria en el siguiente método:

- (id)allStackVariables { 
    int myInt = 0; 
    float myFloat = 0.0f; 
    float* myFloatPtr = NULL; 
    NSObject* myObject = nil; 
} 

lo establece a nil simplemente establece el contenido de la variable a lo que el compilador define como nil, algo así como 0x000000 en hexadecimal. Decir DooDad* dooDad = nil; es conceptualmente idéntico a decir algo como int myInt = 0;

Cuestiones relacionadas