空NSArray是平等的吗?

时间:2011-10-26 19:45:10

标签: objective-c ios nsarray

我在想,为什么这段代码:

NSArray *emptyArr = [[[NSArray alloc] init] autorelease];
NSArray *emptyArrA = [NSArray arrayWithArray:emptyArr];
NSArray *emptyArrB = [NSArray arrayWithArray:emptyArr];

NSLog(@"emptyArrA == emptyArrB => %d", (emptyArrA == emptyArrB));
NSLog(@"emptyArr == emptyArrB => %d", (emptyArr == emptyArrB));
NSLog(@"emptyArrA == emptyArr => %d", (emptyArrA == emptyArr));

输出以下内容:

emptyArrA == emptyArrB => 1
emptyArr == emptyArrB => 1
emptyArrA == emptyArr => 1

也就是说,这些对象似乎是不同的?嗯,我想,这必须是对不可变的空NSArray的特殊情况的iOS(或CoreFoundation?)优化,然后它总是解析为同一个对象实例。

但是......这段代码:

NSLog(@"emptyArr => %p", &emptyArr);
NSLog(@"emptyArrA => %p", &emptyArrA);
NSLog(@"emptyArrB => %p", &emptyArrB);

输出(在我的机器上):

emptyArr => 0xbfffdd64
emptyArrA => 0xbfffdd60
emptyArrB => 0xbfffdd5c

对我来说,表示3个不同的实例。

为什么“==”操作符告诉我它们是相同的对象?

是否是聪明的编译器优化?

- UPDATE -

鉴于以下答案,我仍然有点困惑:-)。我会在这里扩展我的问题..

答案告诉我,“& arrayObject”获取变量的地址,而不是对象,我想这段代码告诉我这是真的:

NSLog(@"emptyArr => %p", &*emptyArr);
NSLog(@"emptyArrA => %p", &*emptyArrA);
NSLog(@"emptyArrB => %p", &*emptyArrB);

因为它输出:

emptyArr => 0x6829fd0
emptyArrA => 0x6829fd0
emptyArrB => 0x6829fd0

表示同一个对象。但这表明(至少对我来说)NSObject实例的“==”运算符中存在某种“魔力”,它实际上使它比较指向变量后面的对象的指针而不是指向变量的指针。这是对的吗?

因为,如果我用“int *”做同样的事情,我必须取消引用它以获得相等。像这样:

int *i1 = malloc(sizeof(int));
*i1 = 42;
int *i2 = malloc(sizeof(int));
*i2 = 42;

NSLog(@"i1 == i2 => %d", (i1 == i2));
NSLog(@"*i1 == *i2 => %d", (*i1 == *i2));

给了我:

i1 == i2 => 0
*i1 == *i2 => 1

这也是我对我(有点过时的)C经历的期望: - )

3 个答案:

答案 0 :(得分:5)

您的第二次测试采用变量的地址,并正确指出有三个不同的变量。所有三个变量都指向同一个空数组实例 - 作为优化,NSArray总是返回相同的空数组,而NSArrays上的arrayWithArray:只保留参数,因为它是不可变的,因此无论如何它们都是无法区分的。如果要查看,请在所有日志语句中取出&运算符。如果您已经测试过&emptyArrA == &emptyArrB,那么您也会看到错误。


回答你的新问题:不,没有魔力。这只是正常的指针相等。当您撰写somePointer == someOtherPointer时,它始终会告诉您他们是否指向相同的地址,无论类型如何 - intBOOLNSMutableAttributedString*,任何类型。它比较了存储在指针中的地址。它绝不会比较指针的神奇指针。

我认为你缺少的是对象总是被指针引用 - 它们永远不是像int这样的直接值。要测试对象的值是否相等而不是指针相等,您需要一个像isEqual:

这样的方法

答案 1 :(得分:2)

这似乎是一种优化:NSArrays是不可变的,因此所有空NSArrays都是等效的,编译器决定不为emptyArrA和emptyArrB创建新实例。

请注意,三个NSArray指针都指向同一个实例,但是您显示的变量地址不是指向的对象的地址。这让你感到困惑。

答案 2 :(得分:0)

emptyArr,emptyArrA和emptyArrB是三个不同的变量,因此获取它们的地址将始终不同。似乎所有这三个变量都包含对同一个空数组对象的引用,就像在等式检查中验证的那样