Pergunta

O que é a diferença entre id e void *?

Foi útil?

Solução

meios void * "uma referência a algum aleatório pedaço o' memória com conteúdo sem tipo / desconhecidos"

meios id "uma referência a um objeto Objective-C aleatória de classe desconhecida"

Existem diferenças semânticas adicionais:

  • Sob GC Apenas ou GC modos suportados, o compilador irá emitir barreiras gravação para referências de tipo id, mas não para o tipo void *. Ao declarar estruturas, esta pode ser uma diferença crítica. Declarando IVARS como void *_superPrivateDoNotTouch; causará colheita prematura de objectos se _superPrivateDoNotTouch é na verdade um objecto. Não faça isso.

  • tentar chamar um método em uma referência do tipo void * vai vomitar-se um aviso do compilador.

  • tentar chamar um método em um tipo id só irá alertar se o método que está sendo chamado não foi declarado em qualquer das declarações @interface visto pelo compilador.

Assim, nunca se deve referir a um objeto como um void *. Da mesma forma, deve-se evitar o uso de uma variável id digitado para se referir a um objeto. Use o máximo de referência digitado classe específica que puder. Mesmo NSObject * é melhor do que id porque o compilador pode, pelo menos, proporcionar uma melhor validação de invocações de método contra essa referência.

A única comum e válido uso de void * é como uma referência de dados opaco que é passado através de algum outro API.

Considere o método sortedArrayUsingFunction: context: de NSArray:

- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;

A função de classificação seria declarado como:

NSInteger mySortFunc(id left, id right, void *context) { ...; }

Neste caso, o NSArray simplesmente passa o que você passar como argumento context ao método através como o argumento context. É um pedaço opaca de ponteiro dimensionado dados, tanto quanto NSArray está em causa, e você está livre para usá-lo para qualquer fim que você quer.

Sem uma característica tipo de fechamento na língua, esta é a única maneira de levar consigo um pedaço de dados com uma função. Exemplo; se você queria mySortFunc () para condicionalmente tipo como insensível caso sensível ou caso, ao mesmo tempo, continua a ser thread-safe, você deve passar o indicador está-case-sensitive no contexto, provavelmente fundição sobre a forma e saída.

Frágil e sujeito a erros, mas a única maneira.

Blocos resolver este - Os blocos são fechos para C. Eles estão disponíveis em Clang - http://llvm.org/ e estão presentes em Snow Leopard ( http: / /developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf ).

Outras dicas

id é um ponteiro para um objeto C objetiva, onde, como void * é um ponteiro para nada.

id também desliga os avisos relacionados a chamar mthods desconhecidos, assim, por exemplo:

[(id)obj doSomethingWeirdYouveNeverHeardOf];

não vai dar o aviso habitual sobre os métodos desconhecidos. Será, naturalmente, gerar uma exceção em tempo de execução, a menos que obj é nula ou realmente implementar esse método.

Muitas vezes você deve usar NSObject* ou id<NSObject> de preferência a id, que pelo menos confirma que o objeto retornado é um objeto de cacau, de modo que você pode usar com segurança métodos como reter / release / disparo automático do mesmo.

Se um método tem um tipo de retorno de id você pode devolver qualquer objeto Objective-C.

meios void, o método não retornará nada.

void * é apenas um ponteiro. Você não será capaz de editar o conteúdo no endereço o ponteiro aponta para.

id é um apontador para um objecto Objectivo-C. void * é um ponteiro para qualquer . Você poderia usar void * vez de id, mas não é recomendado porque você nunca conseguiria avisos do compilador para qualquer coisa.

Você pode querer ver stackoverflow.com/ questões / 466777 / o que está-the-diferença, entre-declarando-a-variável-id-e-NSObject e unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html .

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;

O código de cima é de objc.h, assim como a aparência do ID é um exemplo da estrutura e objc_object ponteiro isa pode ligar-se com qualquer objeto Objectivo da Classe C, enquanto void * é apenas um ponteiro sem tipo.

O meu entendimento é que id representa um ponteiro para um objeto enquanto void * pode apontar realmente a qualquer coisa, contanto que você, em seguida, convertê-lo para o tipo que você quiser usá-lo como

Para além do que já disse, há uma diferença entre objetos e ponteiros ligadas à cobrança. Por exemplo, se você quiser colocar algo em NSArray, você precisa de um objeto (do tipo "id"), e você não pode usar um ponteiro de dados brutos lá (do tipo "void *"). Você pode usar [NSValue valueWithPointer:rawData] para void *rawDdata convertido para o tipo "id" para usá-lo dentro de uma coleção. Em "id" em geral é mais flexível e tem mais semântica relacionados a objetos ligados a ele. Há mais exemplos que explicam tipo ID de Objective C aqui .

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