the compiler is smart, and instead of creating dozens of different NSString instances that all hold the same value he creates one instance that can't be released and all the other instances just point to the NSString that is hardcoded in your program.
And because the hardcoded NSString gets never deallocated you can use it even after the autorelease pool would have deallocated it.
This just covers your wrong memory management. And you should definitely not rely on this behaviour.
Edit. there is not much more to say. The NSString that you've created with stringWithString:literal will simply point to the location of literal in memory.
A little example:
NSString *string = @"Foo";
NSLog(@"%@ - %p", string, string);
NSString *string2 = string;
NSLog(@"%@ - %p", string2, string2);
NSString *string3 = [string copy];
NSLog(@"%@ - %p", string3, string3);
NSString *string4 = [string retain];
NSLog(@"%@ - %p", string4, string4);
NSString *string5 = [NSString stringWithString:string];
NSLog(@"%@ - %p", string5, string5);
NSString *string6 = [[NSString alloc] initWithString:string];
NSLog(@"%@ - %p", string6, string6);
you will see they all point to the same address.
2011-02-22 13:24:41.202 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.207 xxx[40783:207] Foo - 0x74120
And all of them will never get deallocated. So you could access string5 from some other method in your code and it would still point to the address 295740, and the NSString "Foo" would still be there.
But a NSString object that does not point to a string literal would be deallocated at this time, and you would get a bad access exception.
You are violating the memory management rules but you will never notice it if you only use string literals. Until the behaviour of the compiler changes.
So do it right, learn proper memory management and don't rely on internals. Retain all your autoreleased objects if you need them later. Even if they point to string literals