172

id和 和有什么不一样void *

4

7 回答 7

243

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

id表示“对未知类的一些随机 Objective-C 对象的引用”

还有其他语义差异:

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

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

  • 尝试调用id类型上的方法只会在被调用的方法没有在@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参数传递给方法context。就 NSArray 而言,它是一大块不透明的指针大小的数据,您可以随意将其用于您想要的任何目的。

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

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

块解决了这个问题——块是 C 的闭包。它们在 Clang 中可用——http: //llvm.org/并且在雪豹中普遍存在(http://developer.apple.com/library/ios/documentation/Performance /参考/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf)。

于 2009-08-20T06:22:22.190 回答
21

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

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

[(id)obj doSomethingWeirdYouveNeverHeardOf];

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

通常你应该使用NSObject*orid<NSObject>优先于id,它至少可以确认返回的对象是一个 Cocoa 对象,所以你可以安全地使用诸如 retain/release/autorelease 之类的方法。

于 2009-08-20T06:06:02.130 回答
8

如果一个方法的返回类型是id你可以返回任何 Objective-C 对象。

void意味着,该方法不会返回任何东西。

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

于 2009-08-20T05:53:00.907 回答
8

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

于 2009-08-20T06:19:23.367 回答
4
/// 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 Class 对象绑定,而 void* 只是一个无类型的指针。

于 2015-01-19T09:21:52.017 回答
2

我的理解是 id 代表一个指向对象的指针,而 void * 可以指向任何东西,只要你然后将它转换为你想要使用它的类型

于 2009-08-20T05:54:09.640 回答
0

除了已经说过的之外,与集合相关的对象和指针之间存在差异。例如,如果你想在 NSArray 中放入一些东西,你需要一个对象(“id”类型),并且不能在其中使用原始数据指针(“void *”类型)。您可以使用[NSValue valueWithPointer:rawData]转换void *rawDdata为“id”类型以在集合中使用它。一般来说,“id”更灵活,并且具有更多与附加对象相关的语义。这里有更多解释Objective C 的 id 类型的例子。

于 2016-04-30T06:57:42.763 回答