variable tipos son que programacion matematicas ejemplos definicion datos constantes constante objective-c string

objective-c - tipos - variable constante definicion



¿Cuál es la diferencia entre una constante de cadena y una cadena literal? (3)

Estoy aprendiendo Objective-C y Cocoa y me he encontrado con esta afirmación:

Los marcos de trabajo de Cocoa esperan que las constantes de cadena globales en lugar de los literales de cadena se utilicen para claves de diccionario, nombres de notificación y excepción, y algunos parámetros de método que toman cadenas.

Solo he trabajado en lenguajes de nivel superior, así que nunca tuve que considerar tanto los detalles de las cadenas. ¿Cuál es la diferencia entre una constante de cadena y una cadena literal?


Algunas definiciones

Un literal es un valor, que es inmutable por definición. Ej .: 10
Una constante es una variable o un puntero de solo lectura. por ejemplo: const int age = 10;
Un literal de cadena es una expresión como @"" . El compilador reemplazará esto con una instancia de NSString .
Una constante de cadena es un puntero de solo lectura para NSString . por ejemplo: NSString *const name = @"John";

Algunos comentarios en la última línea:

  • Eso es un puntero constante, no un objeto constante 1 . objc_sendMsg 2 no le importa si califica el objeto con const . Si quieres un objeto inmutable, debes codificar esa inmutabilidad dentro del objeto 3 .
  • Todas las expresiones @"" son de hecho inmutables. Se reemplazan 4 en tiempo de compilación con instancias de NSConstantString , que es una subclase especializada de NSString con una disposición de memoria fija 5 . Esto también explica por qué NSString es el único objeto que se puede inicializar en el momento de la compilación 6 .

Una cadena constante sería const NSString* name = @"John"; que es equivalente a NSString const* name= @"John"; . Aquí, tanto la sintaxis como la intención del programador son incorrectas: const <object> se ignora, y la instancia de NSConstantString ( NSConstantString ) ya era inmutable.

1 La palabra clave const aplica se aplica a cualquier cosa que esté inmediatamente a su izquierda. Si no hay nada a su izquierda, se aplica a lo que sea inmediatamente a su derecha.

2 Esta es la función que utiliza el tiempo de ejecución para enviar todos los mensajes en Objective-C y, por lo tanto, lo que puede usar para cambiar el estado de un objeto.

3 Ejemplo: en const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const no previene la última declaración.

4 El código LLVM que reescribe la expresión es RewriteModernObjC::RewriteObjCStringLiteral en RewriteModernObjC.cpp.

5 Para ver la definición NSConstantString , cmd + haga clic en Xcode.

6 Crear constantes de tiempo de compilación para otras clases sería fácil, pero requeriría que el compilador utilizara una subclase especializada. Esto rompería la compatibilidad con versiones anteriores de Objective-C.

Volver a tu presupuesto

Los marcos de trabajo de Cocoa esperan que las constantes de cadena globales en lugar de los literales de cadena se utilicen para claves de diccionario, nombres de notificación y excepción, y algunos parámetros de método que toman cadenas. Siempre debe preferir las constantes de cadena sobre los literales de cadena cuando puede elegir. Mediante el uso de constantes de cadena, solicite la ayuda del compilador para verificar su ortografía y así evitar los errores de tiempo de ejecución.

Dice que los literales son propensos a errores. Pero no dice que también sean más lentos. Comparar:

// string literal [dic objectForKey:@"a"]; // string constant NSString *const a = @"a"; [dic objectForKey:a];

En el segundo caso, estoy usando claves con punteros const, así que en su lugar [a isEqualToString:b] , puedo hacer (a==b) . La implementación de isEqualToString: compara el hash y luego ejecuta la función C strcmp , por lo que es más lento que comparar los punteros directamente. Por eso las cadenas constantes son mejores: son más rápidas de comparar y menos propensas a errores.

Si también quieres que tu cadena constante sea global, hazlo así:

// header extern NSString *const name; // implementation NSString *const name = @"john";


Usemos C ++, ya que mi objetivo C es totalmente inexistente.

Si escondes una cadena en una variable constante:

const std::string mystring = "my string";

Ahora cuando llamas a métodos, usas my_string, estás usando una constante de cadena:

someMethod(mystring);

O bien, puede llamar directamente a esos métodos con la cadena literal:

someMethod("my string");

La razón, presumiblemente, para que te animen a usar constantes de cadena es porque Objective C no hace "interning"; es decir, cuando utiliza el mismo literal de cadena en varios lugares, en realidad es un puntero diferente que apunta a una copia separada de la cadena.

Para las teclas de diccionario, esto hace una gran diferencia, porque si puedo ver que los dos punteros apuntan a la misma cosa, eso es mucho más barato que tener que hacer una comparación de cadena completa para asegurarse de que las cadenas tengan el mismo valor.

Editar: Mike, en C # las cadenas son inmutables, y las cadenas literales con valores idénticos terminan todas apuntando al mismo valor de cadena. Me imagino que eso también es cierto para otros idiomas que tienen cadenas inmutables. En Ruby, que tiene cadenas mutables, ofrecen un nuevo tipo de datos: símbolos ("foo" vs.: foo, donde el primero es una cadena mutable, y el último es un identificador inmutable que se usa a menudo para las teclas Hash).


En Objective-C, la sintaxis @"foo" es una instancia inmutable y literal de NSString . No hace una cadena constante de un literal de cadena como Mike supone.

Los compiladores Objective-C normalmente hacen cadenas literales internas dentro de las unidades de compilación, es decir, combinan múltiples usos de la misma cadena literal, y el enlazador puede hacer prácticas adicionales en las unidades de compilación que están directamente vinculadas en un solo binario. (Como Cocoa distingue entre cadenas mutables e inmutables, y las cadenas literales siempre son inmutables, esto puede ser sencillo y seguro.)

Por otro lado, las cadenas constantes normalmente se declaran y definen usando una sintaxis como esta:

// MyExample.h - declaration, other code references this extern NSString * const MyExampleNotification; // MyExample.m - definition, compiled for other code to reference NSString * const MyExampleNotification = @"MyExampleNotification";

El punto del ejercicio sintáctico aquí es que puede hacer que los usos de la cadena sean eficientes al asegurar que solo hay una instancia de esa cadena en uso, incluso en múltiples marcos (bibliotecas compartidas) en el mismo espacio de direcciones. (La ubicación de la palabra clave const importante, ya que garantiza que el puntero mismo sea constante).

Si bien la quema de memoria no es tan importante como lo fue en los días de las estaciones de trabajo 68030 de 25MHz con 8MB de RAM, la comparación de cadenas para la igualdad puede llevar tiempo. Asegurar que la mayoría de las cadenas de tiempo sean iguales también será útil con el puntero.

Digamos, por ejemplo, que desea suscribirse a las notificaciones de un objeto por su nombre. Si utiliza cadenas no constantes para los nombres, el NSNotificationCenter publica la notificación podría terminar haciendo muchas comparaciones de cadenas byte por byte al determinar quién está interesado en ellas. Si la mayoría de estas comparaciones se cortocircuitan porque las cadenas que se comparan tienen el mismo puntero, eso puede ser una gran ganancia.