2009-07-23 11 views
10

Acabo de comenzar a aprender el objetivo c y el asterisco me está dando problemas. Cuando miro el código de muestra, en algún momento se usa cuando se declara una variable y otras veces no. ¿Cuáles son las "reglas" para cuando debería ser utilizado? Pensé que tenía algo que ver con el tipo de datos de la variable. (Se necesita un asterisco para los tipos de datos de objeto, no necesarios para tipos de datos simples como int) Sin embargo, he visto tipos de datos de objetos como CGPoint declarado sin el asterisco también? ¿Hay una respuesta definitiva o tiene que ver con cómo y para qué usa la variable?Cuándo NO se debe usar el asterisco (*) al declarar una variable en el Objetivo C

Respuesta

17

¿Cuáles son las "reglas" de cuándo se debe utilizar?

Utiliza el asterisco para declarar un puntero.

Para un objeto Cocoa, siempre está declarando un puntero, por lo que siempre usa un asterisco. No puedes poner el objeto en sí en la variable; siempre maneja un puntero al objeto.

Para otras cosas, depende de si la variable contendrá el objeto (en el sentido C) o un puntero al objeto en algún otro lugar. Si la variable debe contener el objeto, entonces no lo declaras con un asterisco, porque no estás poniendo un puntero en él. Si debe contener un puntero, entonces lo declaras con un asterisco.

Incluso puede tener un puntero a un puntero; como es de esperar, esto implica múltiples asteriscos. Por ejemplo, NSRect ** es un puntero a un puntero a un NSRect (que es una estructura, no un objeto Cocoa).

Pensé que tenía algo que ver con el tipo de datos de la variable. (se necesita un asterisco para tipos de datos de objeto, no es necesario para tipos de datos simples como int)

Tipo de. El asterisco es necesario para los objetos Cocoa porque solo puede manejar punteros a los objetos Cocoa, nunca a los objetos mismos. Pero las reglas para la declaración no son diferentes para los objetos de Cacao; Son exactamente lo mismo. Utiliza el asterisco cuando quiere una variable de puntero; no lo haces cuando quieres una variable que no sea puntero.

La única excepción, la única diferencia para los objetos Cocoa de las reglas habituales, es que no se puede declarar una variable que contiene el objeto en sí. Es por eso que nunca se ve una variable que contenga un objeto Cocoa en lugar de un puntero a uno: el compilador no lo permitirá.

Sin embargo, he visto tipos de datos de objeto como CGPoint declarado sin el asterisco también?

CGPoint es una estructura, no un objeto de cacao. Como tal, puede declarar una variable que contiene un CGPoint y no un puntero a otro en otro lugar.

+0

Una nota (en gran parte histórica): no todos los sabores de Objective-C requieren 'punteros a los objetos'. Algunos incluso le permitieron crear objetos en la pila en forma de 'objeto NSObject;'. – johne

+0

En gran parte, tal vez, pero no del todo histórico: en GNUstep, IIRC, todavía puede declarar un objeto en la pila. –

+1

Err, no. GNUstep es, para todos los fines prácticos, una biblioteca compartida, esencialmente un clon de AppKit.framework y Foundation.framework (es decir, la especificación 'OpenStep'). GNUstep también tiene su propio tiempo de ejecución (libobjc). El Objective-C "clásico", que definiría como Apples Objective-C 1.0, es un lenguaje sorprendente. Proporciona algunos primitivos simples y pequeños dogmas sobre cómo debes usarlos, lo que no es sorprendente teniendo en cuenta su herencia. La mayoría lo considera como un "superconjunto estricto" de la C sobre el que se superpone. No ocurre lo mismo con ObjC2 (es decir, punteros GC y 'void *', por ejemplo). – johne

6

El asterisco indica que la variable es un puntero a un tipo de datos.

Debería consultar pointers para obtener más información. Son un aspecto muy importante y fundamental de la programación.

+0

Entiendo que significa que es un puntero. Pero mi pregunta es cuándo debería o no debería usar el puntero. – Jason

+0

Depende completamente de la situación. Necesitará utilizar la memoria asignada en el montón si desea devolver un valor de una función, por ejemplo, ya que de lo contrario se recuperaría cuando la función salga. Los punteros también son necesarios para hacer referencia a las matrices. No es una pregunta fácil de responder, Jason. La asignación de pila es útil ya que no tiene que preocuparse tanto por la memoria, pero el uso de objetos asignados por pila no significa que no necesite manejar punteros. Pero básicamente, si su tipo es pequeño y de corta duración, no se moleste con los punteros. Si es grande o de larga vida, usa punteros. – Welbog

7

Creo que primero debería leer un poco sobre la programación C. Objective-C es un superconjunto de C. La razón por la que no usa * para declarar CGPoint es porque CGPoint es una estructura, eche un vistazo en el archivo de encabezado CGGeometry.h.

+1

Esta es la verdadera clave. Para el tipo en cuestión, vaya al archivo .h donde está definido, y mire si es una estructura o una clase. Si es una clase, necesitas el *; si es una estructura, no la necesita para un uso normal, aunque puede hacerlo si lo desea, pero ese es un tema más avanzado. – Amagrammer

+0

Sí, esto es mi culpa. Supuse falsamente que CGPoint era un tipo de datos objeto y esto causó casi toda la confusión sobre mi punto. ¿Hay algo específico que debería buscar en el archivo .h para saber si es y objeto? ¿Es tan fácil como mirar lo que es la superclase? – Jason

+0

@Amagrammer, +1 gracias por ese comentario. –

0

Parece que tienes la regla resuelta: asterisco para el puntero, sin asterisco en caso contrario. El problema es que no existe una regla para determinar si algo como CGPoint requerirá o no un puntero sin mirar el archivo de encabezado. Como dijo Welbog, la verdadera distinción entre cuándo usar/no usar un puntero es si estás asignando en el montón o en la pila, aunque la mayoría de las veces solo necesitarás determinar si estás trabajando con un objeto (asterisco) o un primitivo (sin asterisco).

3

Utiliza un * cuando el tipo de variable es una clase.

Un ejemplo puede ayudar.

NSNumber *number; 
NSInteger integer; 

El NSNumber tipo de variable es una clase mientras NSInteger es otro nombre para un normal de C-tipo int. Como se puede ver aquí, el compilador reemplaza cada ocurrencia de NSInteger con int:

#if __LP64__ || NS_BUILD_32_LIKE_64 
    typedef long NSInteger; 
    typedef unsigned long NSUInteger; 
#else 
    typedef int NSInteger; 
    typedef unsigned int NSUInteger; 
#endif 

Además, no se puede declarar una instancia de una clase (un objeto), como NSNumber, sin necesidad de utilizar un puntero (por lo tanto usa un *). La razón para esto es que cuando se alloc una instancia de una clase como objeto se devuelve una dirección de memoria. Un puntero es un tipo de variable que se refiere específicamente a una ubicación de memoria. Por ejemplo:

NSNumber *number = [NSNumber alloc]; 

Aquí number 's valor numérico sería una posición de memoria como 0x19a30c0. Puede operar agregando y restando, como int. El objetivo principal de declararlo como un puntero NSNumber es que el compilador pueda ayudar al codificador a verificar que la clase tenga ciertos métodos o acceder a las propiedades conocidas.


Un último ejemplo:

NSInteger integer = [NSNumber alloc]; 

¿Cuál sería el valor de integer ser? En nuestro ejemplo, sería 0x19a30c0. Con esto, aún podría acceder al objeto recientemente asignado NSNumber a través del [integer someMethod]. El compilador te daría una advertencia, sin embargo. Más sobre: ​​

integer += 4; 

Esto afectaría el valor numérico 0x19a30c0 mediante la adición de 4 a él y lo que es 0x19a30c4.


vistazo a este artículo de Wikipedia sobre C/C++ pointers para algunos más ejemplos de cómo, cuándo y por qué utilizar un operador *.

+1

En referencia a su pregunta sobre CGPoint, debe saber que CGPoint NO es una clase. Es una estructura. Por lo tanto, puede tener CGPoints estáticos y no modificables asignados para compilar el código. Por otro lado, si dinámicamente asignó un CGPoint durante el tiempo de ejecución, usaría un puntero CGPoint (es decir: CGPoint * cgPointer) para hacer referencia a la variable en la memoria. ¿Tiene sentido? – Brenden

0

La respuesta es muy simple: debe siempre utilice el asterisco cuando use objetos Objective-C.

La razón es que no se pueden asignar en la pila, por lo que no puede hacer lo que puede hacer con estructuras como CGPoint.

Los diseñadores de Objective-C eligieron, supongo, para que siempre agregue ese asterisco porque son punteros a la memoria como otros C-punteros.

Cuestiones relacionadas