2012-01-30 9 views
12

He encontrado varias personas/artículos (por ejemplo, this SO answer) que sugieren que el valor de los punteros en Objective-C no se define hasta que le asigne algo. Sin embargo, yo estoy encontrando en la práctica que se ajustan automáticamente a nil incluso antes de que llame alloc - el código siguiente ejecuta para mí sin afirmar:¿Los punteros siempre están configurados como nulos en la declaración?

NSString* foo;   // 1 
assert(foo==nil);  // foo is nil 
foo = [NSString alloc]; // 2 
assert(foo!=nil);  // after alloc, not nil. 
foo = [foo init];  // 3 
assert(foo!=nil);  // still not nil 

CAN/debo confiar en esto? ¿Está garantizado o simplemente estoy ejecutando mi compilador (Xcode) en algún tipo de modo de depuración? (Soy nuevo en Objective-C).

Una pregunta corolario: ¿cuál es la terminología correcta para describir foo en el estado al final de las líneas marcadas 1, 2 y 3? Me imagino que al menos uno de 1 & 2 se denomina 'no inicializado', y uno de 2 & 3 se 'inicializa', pero ¿a qué llamamos la tercera opción?

+0

después de objeto alloc y normalmente no == nil . es igual a cero es un error – theWalker

+1

Posible duplicado de http://stackoverflow.com/questions/3989377/xcode-compiler-doesnt-set-my-variable-and-pointer-initial-value-to-0-or-nil –

Respuesta

25

Bajo ARC, todo objeto punteros se establecen en nil tras la inicialización. Cuando no se ejecuta bajo ARC, o cuando se utilizan punteros a otros tipos de datos, un puntero no inicializado tendrá un valor de desecho (y de hecho la lectura del puntero produce un comportamiento indefinido de acuerdo con el estándar C).


@Chuck señala algo importante, que es que esto sólo se aplica a las variables locales. Cualquier variable con almacenamiento estático (función estática o globales) y variables de instancia siempre se inicializan a su valor cero respectivo (que, para los indicadores, es nil/NULL).

+7

Tenga en cuenta que esto solo se aplica a variables locales no estáticas. Las variables globales, estáticas y de instancia de los tipos de objeto * se inicializarán a cero de acuerdo con el estándar. – Chuck

+0

@Chuck: Muy buen punto. Actualizaré mi respuesta en consecuencia. –

+0

¿Puede vincular a la documentación que lo indica por favor? Pensé que el enlace ARC lo tendría, pero no parece (busqué en la página 'nil') – bacar

6

(Para ARC, véase la respuesta de Kevin)

puede/debería depender de esto?

No, nunca confíes en eso. La memoria de pila generalmente se pone a cero en las compilaciones de depuración (depende de la configuración del compilador). Con la optimización habilitada, el compilador no hace eso por ti y se te darán valores de basura basados ​​en lo que sea que haya pasado en la última región de la pila.

Usted puede depender reducidos a cero Ivars en inicializadores de tus objetos.

Puede protegerse de esto con el analizador estático y habilitando -Wuninitialized para sus configuraciones de compilación cuando el nivel de optimización es mayor que -O0.

Una pregunta corolario: ¿cuál es la terminología correcta para describir foo en el estado al final de las líneas marcadas 1, 2 y 3? Me imagino que al menos uno de 1 & 2 se denomina 'no inicializado', y uno de 2 & 3 se 'inicializa', pero ¿a qué llamamos la tercera opción?

  1. sin inicializar
  2. Una instancia objc que ha sido asignado, pero no se ha inicializado (no seguro de usar de otro modo)
  3. Una instancia objc inicializado o un objeto.
+0

I Intentaré activarlos si puedo averiguar cómo, luego publico de nuevo, solo para verificar, ¿también desactiva las afirmaciones? – bacar

+0

@bacar: la desactivación de las afirmaciones se realiza con la macro del compilador 'NS_BLOCK_ASSERTIONS'. –

+0

¿Alguna vez hay una situación en la que un puntero sea automáticamente nulo? Si no, esto alivia la mayoría de las preocupaciones que he tenido sobre el envío de mensajes a cero ... – bacar

1

una respuesta a su pregunta corolario:

Después de # 1, foo ha sido declarado pero es sin inicializar.

Tras # 2, que nombre ha sido asignado pero que están todavía sin inicializar .

Después de # 3, foo ha sido inicializado.

En la práctica, nunca debe separar los pasos 2 y 3, es decir, su código debe ser foo = [[NSString alloc] init]. La razón de esto es que es "peligroso" asignar un objeto y no inicializarlo, o inicializarlo incorrectamente.

Si solo hace esto foo = [NSString alloc], pero olvide llamar a init, no es seguro usar foo ya que no se ha inicializado. Del mismo modo, tampoco es seguro hacer esto [foo init] (observe la falta de reasignación a foo) porque init puede devolver una referencia diferente al objeto inicializado que asignó originalmente por alloc.

+0

¿Está esta terminología documentada en algún lugar, en un libro o simplemente algo que haya observado en la comunidad? – bacar

+0

Es terminología estándar de informática. – UIAdam

+0

OK :-) Vengo de un fondo C++/C# donde los objetos están construidos o no, no hay 'entre'. – bacar

0

En ARC, los objetos de entorno se establecen automáticamente en cero. Pero siempre es una buena práctica asignar valor a los objetos durante la inicialización.

que acaba de ejecutar una prueba con obj-c en el entorno ARC

NSString *testStr ; 
if (testStr == nil) { 
    NSLog(@"Test Successful"); 
} 

OutPut : se inicia la prueba con éxito

NSString *testStr = nil; 
if (testStr == nil) { 
    NSLog(@"Test Successful"); 
} 

OutPut : prueba exitosa

Cuestiones relacionadas