无法理解NSError/NSObject指针传递行为

Bor*_*ris 6 pointers objective-c nserror ios

我现在对指针的指针很困惑,即使我已经读过为什么NSError需要双重间接?(指向指针的指针)NSError*vs NSError**等等.

我做了一些思考,仍然有一些问题.

在这里我写了这个:

NSError *error = [NSError errorWithDomain:@"before" code:0 userInfo:nil];
NSLog(@"outside error address: %p", &error];
[self doSomethingWithObj:nil error:&error];
Run Code Online (Sandbox Code Playgroud)

为了测试上面的NSError方法,我写了这个:

- (id)doSomethingWithObj:(NSObject *)obj error:(NSError *__autoreleasing *)error
{
    NSLog(@"inside error address: %p", error);
    id object = obj;
    if (object != nil)
    {
        return object;
    }
    else
    {
        NSError *tmp = [NSError errorWithDomain:@"after" code:0 userInfo:nil];
        *error = tmp;
        return nil;
    }
}
Run Code Online (Sandbox Code Playgroud)

但我发现两个日志记录地址不同.这是为什么?

2016-08-19 19:00:16.582 Test[4548:339654] outside error address: 0x7fff5b3e6a58
2016-08-19 19:00:16.583 Test[4548:339654] inside error address: 0x7fff5b3e6a50
Run Code Online (Sandbox Code Playgroud)

它们不应该是相同的,因为那只是一个简单的价值副本吗?如果它们应该不同,指向指针的指针最终如何指向同一个NSError实例?

nck*_*cke 0

因此,在第一行初始化之后,error是一个指向NSError对象的指针。

在第一个日志中,您将记录该指针所在的地址。这就是 & 地址运算符的作用。不管怎样,地址被传递到 doSomething 方法中。

您正在传递:指针 -> 指针 -> nserror-object。

但请注意doSomething 签名中的双重间接。自动释放注释使其很难被发现,但它的NSError **.

因此,编译器会获取您的参数并将其“展开”两次。

它以指针 -> 指针 -> nserror-object 开始。然后在第一次间接寻址之后,它变成指针 -> nserror-object。然后在第二次间接之后它变成 nserror-object。

因此,您正在记录两件不同的事情。第一个是指向 nserror 对象的指针的地址。第二个是 nserror 对象本身的地址。

编辑:@MANIAK_dobrii 指出所指向的对象本身在前后情况下error是不同的。

这是真的。如果 doSomething 中发生错误,那么它会在 else 子句中创建一个全新的 NSError 实例。然后它将其加载回error指针。这就是为什么您会看到两个不同的地址,然后error指针完全指向另一个对象。