この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
Objective-CのNSStringなポインタ変数をcopyしても、メモリに新しく領域が確保されるわけではなく、同じアドレスを指し示すという事を聞いたので、本当なのか調べてみた。比較の為、NSMutableStringも。
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *foo = @”Hello”;
NSString *copiedFoo = [foo copy];
NSString *retainedFoo = [foo retain];
NSMutableString *bar = [NSMutableString stringWithString:@”World”];
NSMutableString *copiedBar = [bar copy];
NSMutableString *retainedBar = [bar retain];
NSLog(@”foo : %@ (%x, %@, %d)”, foo, foo, [foo className], [foo retainCount]);
NSLog(@”Copied : %@ (%x, %@, %d)”, copiedFoo, copiedFoo, [copiedFoo className], [copiedFoo retainCount]);
NSLog(@”Retained: %@ (%x, %@, %d)”, retainedFoo, retainedFoo, [retainedFoo className], [copiedFoo retainCount]);
NSLog(@”bar : %@ (%x, %@, %d)”, bar, bar, [bar className], [bar retainCount]);
NSLog(@”Copied : %@ (%x, %@, %d)”, copiedBar, copiedBar, [copiedBar className], [copiedBar retainCount]);
NSLog(@”Retained: %@ (%x, %@, %d)”, retainedBar, retainedBar, [retainedBar className], [retainedBar retainCount]);
[pool drain];
return 0;
}
その結果、確かに同じだった。以下は、NSLogでコンソールに出力している内容で、括弧の中身は、左から順にアドレス、クラス名、リテインカウンタになります。
HelloWorld[2106:10b] foo : Hello (2030, NSCFString, 2147483647)
HelloWorld[2106:10b] Copied : Hello (2030, NSCFString, 2147483647)
HelloWorld[2106:10b] Retained: Hello (2030, NSCFString, 2147483647)
HelloWorld[2106:10b] bar : World (105990, NSCFString, 2)
HelloWorld[2106:10b] Copied : World (105a00, NSCFString, 1)
HelloWorld[2106:10b] Retained: World (105990, NSCFString, 2)
NSStringは、後から中身を変更するわけではないので、copyしても、retainと同じなんだなと。逆にNSMutableStringは、後からappendStringなどするのでcopyした場合は、きちんと別にメモリが確保されていますね。
ちなみに、
NSMutableString *bar = @”World”;
[bar appendString:@”hooo”];
とすると、ビルドはできますが実行時に落ちてしまいます。理由は、
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Attempt to mutate immutable object with appendString:’
と、NSMutableStringと宣言したポインタ変数に文字列を代入すると、NSStringになってしまうから。