Objective-C:id 和 void * 之间的区别
id
和 void *
有什么区别?
What is the difference between id
and void *
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
id
和 void *
有什么区别?
What is the difference between id
and void *
?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(7)
void *
表示“对具有无类型/未知内容的某个随机内存块的引用”“对未知类的某个随机 Objective-C 对象的引用”
id
表示 其他语义差异是:在仅 GC 或支持 GC 模式下,编译器将为
id
类型的引用发出写入屏障,但不会为void *
类型的引用发出写入屏障。在声明结构时,这可能是一个关键的区别。如果_superPrivateDoNotTouch
实际上是一个对象,则像void *_superPrivateDoNotTouch;
那样声明 iVar 将导致过早回收对象。不要这样做。尝试在
void *
类型的引用上调用方法将会引发编译器警告。仅当所调用的方法尚未在编译器看到的任何
@interface
声明中声明时,尝试调用id
类型上的方法才会发出警告。因此,永远不应该将对象称为
void *
。同样,应该避免使用 id 类型变量来引用对象。尽可能使用最具体的类类型参考。即使NSObject *
也比id
更好,因为编译器至少可以针对该引用提供更好的方法调用验证。void *
的一种常见且有效的用法是作为通过其他 API 传递的不透明数据引用。考虑
NSArray
的sortedArrayUsingFunction: context:
方法:排序函数将声明为:
在这种情况下,NSArray 仅传递您作为
context 传入的内容
参数通过作为context
参数传递给方法。就 NSArray 而言,它是一大块不透明的指针大小的数据,您可以随意将其用于任何您想要的目的。如果语言中没有闭包类型功能,这是用函数携带大量数据的唯一方法。例子;如果您希望 mySortFunc() 有条件地排序为区分大小写或不区分大小写,同时仍然是线程安全的,您可以在上下文中传递区分大小写的指示符,可能会在传入和传出时进行强制转换。
脆弱且容易出错,但却是唯一的方法。
块解决了这个问题——块是 C 语言的闭包。它们可以在 Clang 中使用——http://llvm.org/并且在 Snow Leopard 中普遍存在(http://developer. apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf)。
void *
means "a reference to some random chunk o' memory with untyped/unknown contents"id
means "a reference to some random Objective-C object of unknown class"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_superPrivateDoNotTouch
is 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
id
type will only warn if the method being called has not been declared in any of the@interface
declarations seen by the compiler.Thus, one should never refer to an object as a
void *
. Similarly, one should avoid using anid
typed variable to refer to an object. Use the most specific class typed reference you can. EvenNSObject *
is better thanid
because the compiler can, at the least, provide better validation of method invocations against that reference.The one common and valid use of
void *
is as an opaque data reference that is passed through some other API.Consider the
sortedArrayUsingFunction: context:
method ofNSArray
:The sorting function would be declared as:
In this case, the NSArray merely passes whatever you pass in as the
context
argument to the method through as thecontext
argument. 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.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.
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).
id 是一个指向目标 C 对象的指针,而 void* 是一个指向任何内容的指针。
id 还会关闭与调用未知方法相关的警告,因此例如:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
不会给出有关未知方法的常见警告。当然,它会在运行时引发异常,除非 obj 为 nil 或者确实实现了该方法。
通常,您应该优先使用
NSObject*
或id
而不是id
,这至少可以确认返回的对象是 Cocoa 对象,所以你可以安全地使用保留/释放/自动释放等方法。id is a pointer to an objective C object, where as void* is a pointer to anything.
id also turns off warnings related to calling unknown mthods, so for example:
[(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.
Often you should use
NSObject*
orid<NSObject>
in preference toid
, which at least confirms that the object returned is a Cocoa object, so you can safely use methods like retain/release/autorelease on it.如果方法的返回类型为 id,您可以返回任何 Objective-C 对象。
void
表示该方法不会返回任何内容。void *
只是一个指针。您将无法编辑指针指向的地址上的内容。If a method has a return type of
id
you may return any Objective-C object.void
means, the method won't return anything.void *
is just a pointer. You won't be able to edit the content on the address the pointer points to.id
是一个指向 Objective-C 对象的指针。void *
是一个指向任何东西的指针。您可以使用void *
代替id
,但不建议这样做,因为您永远不会收到任何编译器警告。您可能想查看 stackoverflow.com/questions/466777 /declaring-a-variable-id-and-nsobject 之间的区别 和 unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html。
id
is a pointer to an Objective-C object.void *
is a pointer to anything. You could usevoid *
instead ofid
, but it's not recommended because you'd never get compiler warnings for anything.You may want to see stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject and unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html.
上面的代码来自 objc.h,所以看起来 id 是 objc_object 结构体的实例,isa 指针可以与任何 Objective C 类对象绑定,而 void* 只是一个无类型指针。
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.
我的理解是 id 代表一个指向对象的指针,而 void * 可以实际指向任何东西,只要你将它转换为你想要使用它的类型
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
除了已经说过的之外,与集合相关的对象和指针之间还有区别。例如,如果您想将某些内容放入 NSArray 中,则需要一个对象(类型为“id”),并且不能在那里使用原始数据指针(类型为“void *”)。您可以使用
[NSValue valueWithPointer:rawData]
将void *rawDdata
转换为“id”类型,以便在集合中使用它。一般来说,“id”更灵活,并且具有更多与其附加的对象相关的语义。 这里有更多示例解释 Objective C 的 id 类型。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 convertvoid *rawDdata
to 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.