目标 C: id 和 void * 之间的区别

idvoid *有什么不同?

72292 次浏览

如果方法的返回类型为 id,则可以返回任何 Objective-C 对象。

void意味着,该方法不会返回任何内容。

void *只是一个指针。您将无法编辑指针指向的地址上的内容。

我的理解是,id 表示一个指向对象的指针,而 void * 可以指向任何东西,只要您将其强制转换为您希望将其用作的类型

Id 是指向目标 C 对象的指针,其中 void * 是指向任何对象的指针。

Id 还会关闭与调用未知方法相关的警告,例如:

[(id)obj doSomethingWeirdYouveNeverHeardOf];

不会对未知方法给出通常的警告。当然,它会在运行时引发异常,除非 obj 为 nil 或者确实实现了该方法。

通常应该优先使用 NSObject*id<NSObject>而不是 id,后者至少可以确认返回的对象是 Cocoa 对象,因此可以安全地对其使用诸如 keep/release/autorelease 之类的方法。

id是一个指向 Objective-C 对象的指针。void *是指向 什么都行的指针。您可以使用 void *而不是 id,但是不推荐这样做,因为您永远不会得到任何编译器警告。

你可能想看看 Stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobjectUnixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html

void *的意思是“对某个内存块的引用,其中包含未输入/未知的内容”

id表示“对某个未知类别的随机 Objective-C 对象的引用”

另外还有一些语义上的差异:

  • 在“仅支持 GC”或“支持 GC”模式下,编译器将为 id类型的引用发出写屏障,但不会为 void *类型的引用发出写屏障。在声明结构时,这可能是一个关键的区别。如果 _superPrivateDoNotTouch实际上是一个对象,那么像 void *_superPrivateDoNotTouch;这样声明 iVar 会导致过早收获对象。别这样。

  • 试图对 void *类型的引用调用方法将会产生一个编译器警告。

  • 试图调用 id类型的方法时,只有在所调用的方法未在编译器看到的任何 @interface声明中声明时才会发出警告。

因此,永远不要将对象称为 void *。类似地,应该避免使用 id类型的变量来引用对象。尽可能使用最具体的类类型化引用。甚至 NSObject *也比 id好,因为编译器至少可以针对该引用提供更好的方法调用验证。

void *的一个常见而有效的用法是作为通过其他 API 传递的不透明数据引用。

考虑 NSArraysortedArrayUsingFunction: context:方法:

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

排序函数将声明为:

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

在这种情况下,NSArray 只是将作为 context参数传递给方法的任何内容作为 context参数传递给方法。就 NSArray 而言,它是一大块不透明的指针大小的数据,您可以自由地将它用于任何需要的目的。

如果语言中没有闭包类型特性,那么这是用函数携带大量数据的唯一方法。例如,如果您希望 mySortFunc ()有条件地排序为区分大小写或不区分大小写,同时仍然是线程安全的,那么您可以在上下文中传递 is-case 敏感指示符,可能会在进入和退出时进行强制转换。

脆弱且容易出错,但唯一的办法。

块可以解决这个问题,块是 C 的闭包。它们在 Clang-http://llvm.org/中可用,在 Snow Leopard (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf)中也很普遍。

/// 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;

上面的代码来自 objecc.h,所以看起来 id 是 obc _ object struct 的一个实例,isa 指针可以绑定到任何 Objective C Class 对象,而 void * 只是一个非类型化的指针。

除了已经说过的内容之外,与集合相关的对象和指针之间也有区别。例如,如果要将某些内容放入 NSArray 中,则需要一个对象(类型为“ id”) ,并且不能在其中使用原始数据指针(类型为“ void *”)。您可以使用 [NSValue valueWithPointer:rawData]void *rawDdata转换为“ id”类型,以便在集合中使用它。一般来说,“ id”更加灵活,与附加到它上面的对象有更多的语义关系。还有更多解释 目标 C 的 id 类型的例子。