You have created a "true pointer", the problem is that the statement:
test2 = @"What the?";
is creating a new string object and assigning the pointer to the new string into the variable test2, test still contains the old pointer.
You could create a pointer to a pointer to solve this problem. Alternatively you could use an NSMutableString and then only use the NSMutableString methods to change (mutate) the string rather than reassigning new values to the test and test2 variables.
The following would be the NSMutableString version of your example:
NSString *test2 = [[NSMutableString alloc] initWithString:@"yo"];
NSString *test = test2;
NSLog(@"test: %@ test2: %@", test, test2);
[test2 setString:@"what the?"];
NSLog(@"test: %@ test2: %@", test, test2);
Which produces the output:
2012-11-14 10:06:27.231 Untitled 2[592:707] test: yo test2: yo
2012-11-14 10:06:27.232 Untitled 2[592:707] test: what the? test2: what the?
NSStrings have some extra syntactic sugar in Objective-C so that both the following have the same effect (although what happens in the background could be completely different or the same).
NSString *test = [NSString alloc] initWithString:@"Hello World"];
NSString *test = @"Hello World";
Both of these statements create a new immutable (unchangeable) string. Creating an NSString using the statement [NSString alloc] init] creates an empty string which is usually not what you want to do.
This means that, in your example where the first two lines are:
NSString*test2=[[NSString alloc]init];
test2=@"yo";
The first line is unnecessary as you are creating a string object and placing the pointer in test2 and then immediately overwriting that pointer with a pointer to the string created by @"yo". If you aren't using ARC this would cause a memory leak as the string created by [[NSString alloc] init] hasn't been released. However, NSString doesn't really work the same as other objects so rather than leaking memory it would probably be more correct to say you are wasting memory"