为什么有些变量在 Objective-C 中用 * 星号声明

Why Some Variables are Declared with an * Asterisk in Objective-C

我才刚刚开始学习Objective-C。我很困惑地看到某些类型的变量有时用 * 星号声明,而另一些则没有。例如,这些是用 *:

声明的
@property NSString *firstName;
NSString * mainString = @"Hello World!";
NSNumber *longNumber = @42l;
NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];

而这些不是:

int someInteger = 42;
NSInteger anInteger = 64;
id firstObject = @"someString";
NSRange substringRange = [mainString rangeOfString:@"long"];

我从 Apple 的文档中找到了这个解释:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1

Both these properties are for Objective-C objects, so they use an asterisk to indicate that they are C pointers.

但是这个解释过于笼统和模糊,我无法理解这个概念。我知道 type * 表示它是一个指针类型,这个类型存储那个类型的指针。但为什么有些类型用 * 声明,有些则没有?

int 类型不是对象。它是一种 C 语言的“原始数据类型”。您通常直接与原始 C 数据类型交互。例如,

int i = 0;   // it’s now `0`
i = 42;      // it’s now `42`

NSInteger 只是另一种原始数据类型 long 的别名。 NSRange 是一个结构(因此,也不是一个对象),所以同样的规则适用。因此,对于与这些原始数据类型的基本交互,通常不需要 * 指针引用。 (实际上有时您还会处理指向原始数据类型的指针,但这超出了本问题的范围。)

但是NSStringNSNumberNSArray,但是,对象,所以声明时必须使用指针。


请注意,您已将 id 包含在未使用 * 的后一个列表中:

id firstObject = @"foo";

要非常小心。这实际上有点误导,因为 firstObject 实际上 指向 @"someString" 的指针,一个 NSString 对象。 id 是我们通常使用 * 声明指针的方式的一个例外,并在 Objective-C is a Dynamic Language) 中进行了讨论,“id 类型定义了一个通用对象指针。”

这类似于声明一个 NSString 指针,但是“你丢失了有关该对象的编译时信息”。将指向 NSString *id 指针与以下语法进行比较:

NSString *secondObject = @"bar";

后面的secondObjectNSString *指针,但是因为我们明确声明它是一个NSString *指针,所以编译器知道你正在处理一个字符串(因此编译器可以对该指针的后续使用执行更大的验证)。使用 id,您不享受此编译时验证。

例如,这里有两次对两个 NSString 对象调用 removeObject 方法的无效尝试。 NSString没有这样的方法。 NSString * 参考提供了有用的编译时错误消息,id 没有提供给我们:

现在,如果您使用 id 类型并尝试 运行 该代码,它会在尝试调用 firstObject 上的 removeObject 时崩溃。但是,在可能的情况下,让编译器在编译时告诉我们错误要好得多,而不是在 运行-time.

所以应该谨慎使用 id 模式,只有当你真的需要 Objective-C 的动态类型行为时才使用。