我碰巧偶然发现了关于使用**
的双星(NSError
)用法的帖子。决定深入挖掘一下,这让我重新审视C
。
我已经在<{1}}上阅读了很多帖子(此处不重复),我理解他们为何会这样做。
所以,我决定在IDE(Xcode)中编写一个小片段,以便自己查看它。
NSError
方法:
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);
输出:
之前:a是: 10 b是: 20
之后:a是: 33 b是: 22
- (void)testDoubleStar:(int**)x
{
int anotherValue1 = 22;
**x = anotherValue1;
}
- (void)testSingleStar:(int*)x
{
int anotherValue2 = 33;
*x = anotherValue2;
}
(通过单个指针)和a
(通过双指针)的值都发生了变化。
所以,如果我们可以使用 仅使用单个指针 来更改(b
)的值,为什么我们需要使用指向指针的指针到a
以便我们可以在方法调用中修改NSError
对象,其中NSError
对象在其参数(NSError
)中传递?
此外:
关于上述内容,将一些内容传递给&error
中的参数实际上是将一个副本传递给参数(即使在单个指针的情况下,只有一个副本会被传递),所以任何改变在方法范围内制作的不会影响传递给它的原始值(这就是他们使用双星的原因)。
但上面的示例(其中只使用了一个指针)似乎与此相矛盾,因为单个指针(C
)指向的值(即a
确实发生了变化?
答案 0 :(得分:4)
您可以通过向函数或方法提供foo
来修改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;
请参阅?情况也是如此:要修改类型foo
,请提供foo*
。
答案 1 :(得分: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.
}