Why do we need pointer to pointer aka double indirection?

In an effort to better grasp why double indirection is needed, e.g., (NSError **), I wrote up a little sample code:

- (void)doFirstThingWith:(NSMutableString *)string {
    // Set local string pointer to the newly created string.
    // note: This DOES NOT affect the string pointer outside of this scope!
    string = [@"first" mutableCopy];
}

- (void)doSecondThingWith:(NSMutableString *)string {
    // Directly modify referenced string.
    [string replaceCharactersInRange:NSMakeRange(0, string.length) withString:@"second"];
}

- (void)doThirdThingWith:(NSMutableString **)string {
    // Update referenced pointer to point to the newly created string.
    *string = [@"third" mutableCopy];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSMutableString *string = [@"before" mutableCopy];
    
    [self doFirstThingWith:string];
    NSLog(@"doFirstThingWith: %@", string);
    
    // doFirstThingWith is basically doing this:
    NSMutableString *string2 = string;
    string2 = [@"first" mutableCopy];    
    NSLog(@"doFirstThingWith: %@", string);

    [self doSecondThingWith:string];
    NSLog(@"doSecondThingWith: %@", string);
    
    [self doThirdThingWith:&string];
    NSLog(@"doThirdThingWith: %@", string);
}

The resulting output:

2012-03-24 18:06:37.071 PointerTest[1195:707] doFirstThingWith: before
2012-03-24 18:06:37.072 PointerTest[1195:707] doFirstThingWith: before
2012-03-24 18:06:37.073 PointerTest[1195:707] doSecondThingWith: second
2012-03-24 18:06:37.073 PointerTest[1195:707] doThirdThingWith: third

We see that doFirstThingWith does not update the passed in string, this is because we are actually updating the method's local string pointer instead of the original string pointer.

In doSecondThingWith, we see that we can update the referenced object and have the changes stick. This concept is already familiar to most of us.

In doThirdThingWith, we use a pointer to the original string pointer. This way, we can update the original pointer to point to a newly created string. Using double indirection gives us a mechanism to return newly created objects via method arguments, this being one of its practical uses.

Check out these links for more information: