Objective-C:id 和 void * 之间的区别

发布于 2024-08-02 23:31:08 字数 51 浏览 8 评论 0原文

idvoid * 有什么区别?

What is the difference between id and void *?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

风透绣罗衣 2024-08-09 23:31:08

void * 表示“对具有无类型/未知内容的某个随机内存块的引用”

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

id表示 其他语义差异是:

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

  • 尝试在 void * 类型的引用上调用方法将会引发编译器警告。

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

因此,永远不应该将对象称为 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() 有条件地排序为区分大小写或不区分大小写,同时仍然是线程安全的,您可以在上下文中传递区分大小写的指示符,可能会在传入和传出时进行强制转换。

脆弱且容易出错,但却是唯一的方法。

块解决了这个问题——块是 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 type void *. When declaring structures, this can be a critical difference. Declaring iVars like void *_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 an id typed variable to refer to an object. Use the most specific class typed reference you can. Even NSObject * is better than id 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 of 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 context argument to the method through as the context 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).

软甜啾 2024-08-09 23:31:08

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* 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.

£烟消云散 2024-08-09 23:31:08

如果方法的返回类型为 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.

仅此而已 2024-08-09 23:31:08

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 use void * instead of id, 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.

一人独醉 2024-08-09 23:31:08
/// 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* 只是一个无类型指针。

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

岁吢 2024-08-09 23:31:08

我的理解是 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

笔芯 2024-08-09 23:31:08

除了已经说过的之外,与集合相关的对象和指针之间还有区别。例如,如果您想将某些内容放入 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 convert void *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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文