Pergunta

Estou aprendendo objetivo-C e Cocoa e me deparei com esta afirmação:

As estruturas Cocoa esperam que constantes de string globais, em vez de literais de string, sejam usadas para chaves de dicionário, nomes de notificação e exceção e alguns parâmetros de método que usam strings.

Eu só trabalhei em linguagens de nível superior, então nunca tive que considerar tanto os detalhes das strings.Qual é a diferença entre uma constante de string e uma string literal?

Foi útil?

Solução

Em Objective-C, a sintaxe @"foo" é um imutável, literal instancia de NSString.Ele não cria uma string constante a partir de uma string literal, como Mike supõe.

Compiladores Objective-C normalmente fazer strings literais internas dentro de unidades de compilação - ou seja, elas reúnem vários usos da mesma string literal - e é possível para o vinculador fazer estágios adicionais nas unidades de compilação que estão diretamente vinculadas em um único binário.(Como Cocoa distingue entre strings mutáveis ​​e imutáveis, e strings literais são sempre imutáveis, isso pode ser direto e seguro.)

Constante strings, por outro lado, são normalmente declaradas e definidas usando uma sintaxe 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";

O objetivo do exercício sintático aqui é que você pode fazer usos de a string é eficiente, garantindo que haja apenas uma instância dessa string em uso mesmo em várias estruturas (bibliotecas compartilhadas) no mesmo espaço de endereço.(A colocação do const palavras-chave são importantes;garante que o próprio ponteiro seja constante.)

Embora queimar memória não seja tão importante como poderia ter sido na época das estações de trabalho 68030 de 25 MHz com 8 MB de RAM, comparar strings quanto à igualdade pode levar tempo.Garantir que a maioria das strings de tempo iguais também sejam iguais a ponteiros ajuda.

Digamos, por exemplo, que você queira assinar notificações de um objeto por nome.Se você usar strings não constantes para os nomes, o NSNotificationCenter postar a notificação pode resultar em muitas comparações de strings byte por byte ao determinar quem está interessado nela.Se a maioria dessas comparações entrar em curto-circuito porque as strings comparadas têm o mesmo ponteiro, isso pode ser uma grande vitória.

Outras dicas

Algumas definições

A literal é um valor imutável por definição.por exemplo: 10
A constante é uma variável ou ponteiro somente leitura.por exemplo: const int age = 10;
A string literal é uma expressão como @"".O compilador substituirá isso por uma instância de NSString.
A constante de string é um ponteiro somente leitura para NSString.por exemplo: NSString *const name = @"John";

Alguns comentários na última linha:

  • Esse é um ponteiro constante, não um objeto constante1. objc_sendMsg2 não se importa se você qualifica o objeto com const.Se você quiser um objeto imutável, terá que codificar essa imutabilidade dentro do objeto3.
  • Todos @"" expressões são de fato imutáveis.Eles são substituídos4 em tempo de compilação com instâncias de NSConstantString, que é uma subclasse especializada de NSString com um layout de memória fixo5.Isto também explica por que NSString é o único objeto que pode ser inicializado em tempo de compilação6.

A sequência constante seria const NSString* name = @"John"; o que equivale a NSString const* name= @"John";.Aqui, tanto a sintaxe quanto a intenção do programador estão erradas: const <object> é ignorado e o NSString instância (NSConstantString) já era imutável.

1 A palavra-chave const aplica-se aplica-se a tudo o que está imediatamente à sua esquerda.Se não houver nada à sua esquerda, aplica-se a tudo o que estiver imediatamente à sua direita.

2 Esta é a função que o tempo de execução usa para enviar todas as mensagens em Objective-C e, portanto, o que você pode usar para alterar o estado de um objeto.

3 Exemplo:em const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const não impede a última instrução.

4 O código LLVM que reescreve a expressão é RewriteModernObjC::RewriteObjCStringLiteral em RewriteModernObjC.cpp.

5 Para ver o NSConstantString definição, cmd + clique no Xcode.

6 Criar constantes de tempo de compilação para outras classes seria fácil, mas exigiria que o compilador usasse uma subclasse especializada.Isso quebraria a compatibilidade com versões mais antigas do Objective-C.


Voltar para sua cotação

As estruturas de cacau esperam que as constantes globais de cordas, em vez de literais de cordas, sejam usadas para chaves de dicionário, nomes de notificação e exceção e alguns parâmetros de método que tomam seqüências.Você sempre deve preferir constantes de string ao alfabetal de string quando tiver uma escolha.Ao usar constantes de string, você recruta a ajuda do compilador para verificar sua ortografia e, assim, evita erros de tempo de execução.

Diz que literais são propensos a erros.Mas isso não significa que eles também sejam mais lentos.Comparar:

// string literal
[dic objectForKey:@"a"];

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

No segundo caso estou usando chaves com ponteiros const, então em vez disso [a isEqualToString:b], Eu posso fazer (a==b).A implementação de isEqualToString: compara o hash e depois executa a função C strcmp, portanto é mais lento do que comparar os ponteiros diretamente.Qual é por que strings constantes são melhores: eles são mais rápidos de comparar e menos sujeitos a erros.

Se você também deseja que sua string constante seja global, faça assim:

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

Vamos usar C++, já que meu Objective C é totalmente inexistente.

Se você armazenar uma string em uma variável constante:

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

Agora, quando você chama métodos, você usa my_string, você está usando uma constante de string:

someMethod(mystring);

Ou você pode chamar esses métodos diretamente com a string literal:

someMethod("my string");

A razão, presumivelmente, pela qual eles encorajam você a usar constantes de string é porque o Objetivo C não faz "estagiário";isto é, quando você usa a mesma string literal em vários lugares, na verdade é um ponteiro diferente apontando para uma cópia separada da string.

Para chaves de dicionário, isso faz uma enorme diferença, porque se eu puder ver que os dois ponteiros estão apontando para a mesma coisa, isso é muito mais barato do que ter que fazer uma comparação de strings inteiras para ter certeza de que as strings têm valor igual.

Editar: Mike, em C# strings são imutáveis, e strings literais com valores idênticos terminam apontando para o mesmo valor de string.Imagino que isso também seja verdade para outras linguagens que possuem strings imutáveis.Em Ruby, que possui strings mutáveis, eles oferecem um novo tipo de dados:símbolos ("foo" vs.:foo, onde o primeiro é uma string mutável e o último é um identificador imutável frequentemente usado para chaves Hash).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top