1

我碰巧在 SO 上偶然发现了关于双星 ( **) 与NSError. 决定更深入地挖掘它,这导致我重新访问C.

我已经在这里阅读了很多帖子(这里不重复)NSError,我理解他们为什么这样做。

因此,我决定在 IDE (Xcode) 中编写一个小片段来亲自查看它的实际效果。

int a = 10;
int b = 20;

int *c = &a;
int *d = &b;

int **e = &d;

NSLog(@"Before: a is: %d b is: %d", a, b);

[self testSingleStar:c]; 
[self testDoubleStar:e]; 

NSLog(@"After: a is: %d b is: %d", a, b);

方法:

- (void)testDoubleStar:(int**)x
{
    int anotherValue1 = 22;
    **x = anotherValue1;
}

- (void)testSingleStar:(int*)x
{
    int anotherValue2 = 33;
    *x = anotherValue2;
}

输出:

之前:a 是:10 b 是:20

之后:a 是:33 b 是:22

a(通过单指针)和b(通过双指针)的值都发生了变化。

那么,如果我们可以只使用单个指针a来更改 (of )的值,为什么我们需要使用指向指针的指针,以便我们可以在方法调用中修改对象在其参数 ( ) 中传递的对象?NSErrorNSErrorNSError&error

此外:

关于上述内容,将某些内容传递给参数 inC实际上是将副本传递给参数(即使在单个指针的情况下,也只会传递它的副本),因此在方法范围内所做的任何更改都会不影响传递给它的原始值(这就是他们使用双星的原因)。

但是上面只使用了一个指针的示例似乎与此相矛盾,因为值(即a由单个指针指向 - c)确实发生了变化?

4

2 回答 2

4

您可以通过向函数或方法foo提供 a来修改类型的外部变量:foo *

+ (void)doJobReturningInt(int *) { ... }

int a;
[MyClass doJobReturningInt:&a]; // may modify the value of the variable a;

到目前为止,一切都很好。

现在我们如何声明一个存储 NSError 对象的变量?使用NSError *类型:

NSError *error;

所以如果我们想修改它,我们需要提供一个指向它的类型的指针,也就是NSError **.

+ (void)doJobReturningError:(NSError **)outError { ... }

NSError *error;
[MyClass doJobReturningError:&error]; // may modify the value of the variable error;

看?这是同样的情况:为了修改 type foo,提供一个foo*.

于 2014-01-08T17:06:15.370 回答
2

这是因为你不能只拥有一个 NSError 对象......你只能通过指针处理 Objective-C 对象......所以虽然理论上你可以获取一个指向 NSError 的指针并交换它的内容......它会搞砸封装(其他事情可能依赖于曾经存在的数据。)。

也只是将指针重新分配给一个新值是行不通的,因为它不会影响调用者的版本。

因此,虽然看起来很诱人:

-(void)method:(NSError *)errObject
{
    //something like
    errObject = [NSError errorWithBlah:@"blah"]; // this will only change the local variable errObject, not the callers version, that pointer is just copied by value. 
}

或者

 /// not real code, didn't check to see if my params are in the correct places etc.
-(void)mangler:(NSError *)errObject
{
    //something like
    errObject = realloc(errObject,sizeof *errorObject);
    memcpy(errObject,[NSError new],sizeof NSError);

    // you have killed the old version that may be in use.
}
于 2014-01-08T17:08:07.283 回答