Цель-C: разница между id и void *


в чем разница между id и void *?

7 165

7 ответов:

void * означает "ссылка на некоторый случайный кусок памяти с нетипизированным / неизвестным содержимым"

id означает "ссылка на некоторый случайный объект Objective-C неизвестного класса"

есть дополнительные семантические различия:

  • в соответствии с ГК или ГК поддерживаемые режимы, компилятор выдаст писать барьеры для ссылки типа id, но не для типа void *. При объявлении структур это может быть критическим различием. Объявляя ивары как void *_superPrivateDoNotTouch; вызовет преждевременную жатву объектов, если _superPrivateDoNotTouch на самом деле объект. Не делай этого.

  • попытка вызвать метод по ссылке void * тип будет рвать предупреждение компилятора.

  • попытка вызвать метод на id тип будет предупреждать только в том случае, если вызываемый метод не был объявлен ни в одном из @interface заявления видно компилятор.

таким образом, никогда не следует ссылаться на объект как void *. Точно так же следует избегать использования id типизированная переменная для ссылки на объект. Используйте наиболее конкретную типизированную ссылку класса, которую вы можете использовать. Даже NSObject * лучше, чем id потому что компилятор может, по крайней мере, обеспечить лучшую проверку вызовов метода против этой ссылки.

одно общее и действительное использование void * как непрозрачная ссылка на данные, которая прошел через какой-то другой API.

рассмотрим sortedArrayUsingFunction: context: метод NSArray:

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

функция сортировки будет объявлена как:

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

в этом случае NSArray просто передает все, что вы передаете в качестве context аргумент к методу через Как

id-это указатель на объект objective C, где as void* - указатель на что-либо.

id также отключает предупреждения, связанные с вызовом неизвестных mthods, например:

[(id)obj doSomethingWeirdYouveNeverHeardOf];

не будет давать обычное предупреждение о неизвестных методах. Это, конечно, вызовет исключение во время выполнения, если obj не равен нулю или действительно не реализует этот метод.

часто вы должны использовать NSObject* или id<NSObject> вместо id, который по крайней мере подтверждает, что возвращаемый объект является объектом Cocoa, поэтому вы можете безопасно использовать такие методы, как retain/release/autorelease на нем.

Если метод имеет тип возвращаемого id вы можете вернуть любой объект Objective-C.

void означает, что метод ничего не вернет.

void * - это просто указатель. Вы не сможете редактировать содержимое по адресу, на который указывает указатель.

id - указатель на объект Objective-C. void * указатель что-нибудь. Вы могли бы использовать void * вместо id, но это не рекомендуется, потому что вы никогда не получите предупреждения компилятора ничего.

вы можете увидеть stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject и 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;

приведенный выше код от objc.h, поэтому похоже, что id является экземпляром структуры objc_object, а указатель isa может связываться с любым объектом класса Objective C, в то время как void* - это просто нетипизированный указатель.

Я понимаю, что id представляет собой указатель на объект, а void * может указывать на что-либо действительно, если вы затем приведете его к типу, который вы хотите использовать как

в дополнение к тому, что уже сказано, есть разница между объектами и указателями, связанными с коллекциями. Например, если вы хотите поместить что-то в NSArray, вам нужен объект (типа "id"), и вы не можете использовать указатель необработанных данных там (типа "void *"). Вы можете использовать [NSValue valueWithPointer:rawData] преобразование void *rawDdata к типу " id " для использования его внутри коллекции. В целом "id" является более гибким и имеет больше семантики, связанной с объектами, прикрепленными к нему. Есть еще примеры, объясняющие id тип цели C здесь.