Objective-C:id 和 void 之间的区别 *
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1304176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Objective-C: difference between id and void *
提问by mk12
What is the difference between idand void *?
id和 和有void *什么区别?
回答by bbum
void *means "a reference to some random chunk o' memory with untyped/unknown contents"
void *意思是“对一些具有未类型化/未知内容的随机内存块的引用”
idmeans "a reference to some random Objective-C object of unknown class"
id表示“对未知类的某个随机 Objective-C 对象的引用”
There are additional semantic differences:
还有其他语义差异:
Under GC Only or GC Supported modes, the compiler will emit write barriers for references of type
id, but not for typevoid *. When declaring structures, this can be a critical difference. Declaring iVars likevoid *_superPrivateDoNotTouch;will cause premature reaping of objects if_superPrivateDoNotTouchis actually an object. Don't do that.attempting to invoke a method on a reference of
void *type will barf up a compiler warning.attempting to invoke a method on an
idtype will only warn if the method being called has not been declared in any of the@interfacedeclarations seen by the compiler.
在 GC Only 或 GC Supported 模式下,编译器将为 type 的引用发出写屏障
id,但不会为 type 的引用发出写屏障void *。在声明结构时,这可能是一个关键的区别。声明 iVars likevoid *_superPrivateDoNotTouch;会导致过早收获对象,如果_superPrivateDoNotTouch它实际上是一个对象。不要那样做。尝试在
void *类型引用上调用方法将导致编译器警告。尝试调用一个
id类型的方法只会在被调用的方法没有@interface在编译器看到的任何声明中声明时发出警告。
Thus, one should never refer to an object as a void *. Similarly, one should avoid using an idtyped variable to refer to an object. Use the most specific class typed reference you can. Even NSObject *is better than idbecause the compiler can, at the least, provide better validation of method invocations against that reference.
因此,永远不应将对象称为void *. 同样,应该避免使用id类型化变量来引用对象。尽可能使用最具体的类类型引用。EvenNSObject *比id因为编译器至少可以针对该引用提供更好的方法调用验证更好。
The one common and valid use of void *is as an opaque data reference that is passed through some other API.
一种常见且有效的用途void *是作为通过其他 API 传递的不透明数据引用。
Consider the sortedArrayUsingFunction: context:method of NSArray:
考虑以下sortedArrayUsingFunction: context:方法NSArray:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
The sorting function would be declared as:
排序函数将被声明为:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
In this case, the NSArray merely passes whatever you pass in as the contextargument to the method through as the contextargument. It is an opaque hunk of pointer sized data, as far as NSArray is concerned, and you are free to use it for whatever purpose you want.
在这种情况下,NSArray 只是将您作为context参数传入的任何内容作为参数传递给方法context。就 NSArray 而言,它是一个不透明的指针大小的数据块,您可以自由地将它用于任何您想要的目的。
Without a closure type feature in the language, this is the only way to carry along a hunk of data with a function. Example; if you wanted mySortFunc() to conditionally sort as case sensitive or case insensitive, while also still being thread-safe, you would pass the is-case-sensitive indicator in the context, likely casting on the way in and way out.
如果语言中没有闭包类型特性,这是使用函数携带大量数据的唯一方法。例子; 如果您希望 mySortFunc() 有条件地排序为区分大小写或不区分大小写,同时仍然是线程安全的,您将在上下文中传递 is-case-sensitive 指示符,可能会在输入和输出中进行转换。
Fragile and error prone, but the only way.
脆弱且容易出错,但这是唯一的方法。
Blocks solve this -- Blocks are closures for C. They are available in Clang -- http://llvm.org/and are pervasive in Snow Leopard (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).
块解决了这个问题——块是 C 的闭包。它们在 Clang 中可用——http: //llvm.org/并且在 Snow Leopard ( http://developer.apple.com/library/ios/documentation/Performance /Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf)。
回答by Peter N Lewis
id is a pointer to an objective C object, where as void* is a pointer to anything.
id 是指向目标 C 对象的指针,而 void* 是指向任何对象的指针。
id also turns off warnings related to calling unknown mthods, so for example:
id 还会关闭与调用未知方法相关的警告,例如:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
[(id)obj doSomethingWeirdYouveNeverHeardOf];
will not give the usual warning about unknown methods. It will, of course, raise an exception at run time unless obj is nil or really does implement that method.
不会给出关于未知方法的通常警告。当然,它会在运行时引发异常,除非 obj 为零或确实实现了该方法。
Often you should use NSObject*or id<NSObject>in preference to id, which at least confirms that the object returned is a Cocoa object, so you can safely use methods like retain/release/autorelease on it.
通常,您应该使用NSObject*或id<NSObject>优先使用id,这至少可以确认返回的对象是 Cocoa 对象,因此您可以安全地在其上使用诸如 retain/release/autorelease 之类的方法。
回答by Michael
idis a pointer to an Objective-C object. void *is a pointer to anything. You could use void *instead of id, but it's not recommended because you'd never get compiler warnings for anything.
id是一个指向 Objective-C 对象的指针。void *是指向任何东西的指针。您可以使用void *代替id,但不推荐使用,因为您永远不会收到任何编译器警告。
You may want to see stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobjectand unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html.
您可能想查看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。
回答by fphilipe
If a method has a return type of idyou may return any Objective-C object.
如果一个方法有一个返回类型,id你可以返回任何 Objective-C 对象。
voidmeans, the method won't return anything.
void意味着,该方法不会返回任何内容。
void *is just a pointer. You won't be able to edit the content on the address the pointer points to.
void *只是一个指针。您将无法编辑指针指向的地址上的内容。
回答by Hyman
/// 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;
The above code is from objc.h, so looks like id is an instance of objc_object struct and isa pointer can bind with any Objective C Class object, while void* is just an untyped pointer.
上面的代码来自 objc.h,所以看起来 id 是 objc_object 结构体的实例,而 isa 指针可以绑定任何 Objective C Class 对象,而 void* 只是一个无类型指针。
回答by hhafez
My understanding is that id represents a pointer to an object while void * can point to anything really, as long as you then cast it to the type you want to use it as
我的理解是 id 代表一个指向对象的指针,而 void * 可以真正指向任何东西,只要你将它转换为你想要使用的类型
回答by battlmonstr
In addition to what's already said, there's a difference between objects and pointers related to collections. For example, if you want to put something into NSArray, you need an object (of type "id"), and you can't use a raw data pointer there (of type "void *"). You can use [NSValue valueWithPointer:rawData]to convert void *rawDdatato the "id" type for using it inside a collection. In general "id" is more flexible and has more semantics related to objects attached to it. There's more examples explaining id type of Objective C here.
除了已经说过的之外,与集合相关的对象和指针之间还有区别。例如,如果你想把一些东西放入 NSArray,你需要一个对象(“id”类型),并且你不能在那里使用原始数据指针(“void *”类型)。您可以使用[NSValue valueWithPointer:rawData]转换void *rawDdata为“id”类型以在集合中使用它。一般来说,“id”更灵活,并且与附加到它的对象相关的语义更多。这里有更多的例子解释了 Objective C 的 id 类型。

