Вопрос

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

Это было полезно?

Решение

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

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

Существуют дополнительные семантические различия:

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

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

  • попытка вызвать метод на id type будет предупреждать только в том случае, если вызываемый метод не был объявлен ни в одном из @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 аргумент метода through в качестве context аргумент.Что касается NSArray, это непрозрачный массив данных размером с указатель, и вы можете свободно использовать его для любых целей, которые вы хотите.

Без функции типа замыкания в языке это единственный способ перенести большой объем данных с помощью функции.Пример;если бы вы хотели, чтобы mySortFunc() выполнял условную сортировку с учетом регистра или без учета регистра, оставаясь при этом потокобезопасным, вы бы передали индикатор is-case-sensitive в контексте, вероятно, применяя его при входе и выходе.

Хрупкий и подверженный ошибкам, но единственный способ.

Блоки решают эту проблему - Блоки являются замыканиями для C.Они доступны в Clang -- http://llvm.org/ и широко распространены у Снежного Барса (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).

Другие советы

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

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

[(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 и юниксджанки.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" является более гибким и имеет больше семантики, связанной с прикрепленными к нему объектами.Есть еще примеры, объясняющие идентификатор типа Objective C здесь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top