例では
NSString *message = @"Hello";
message = @"World";
*message = @"World";
メッセージが単なるポインターである場合、メッセージにあるものはすべて文字列またはCのように等しいと明示的に言う必要がないのはなぜですか?
例では
NSString *message = @"Hello";
message = @"World";
*message = @"World";
メッセージが単なるポインターである場合、メッセージにあるものはすべて文字列またはCのように等しいと明示的に言う必要がないのはなぜですか?
免責事項
以下の説明は、Objective-C でオブジェクトへのポインターを逆参照しない理由についての一般的な考え方を示しています。ただし、リテラルの特定のケースに関してはNSString
、これは実際に起こっていることではありません。以下で説明する構造はまだ健全であり、そのように機能する可能性がありますが、実際に起こっているのは、文字列リテラルのスペースがコンパイル時に割り当てられ、そのアドレスが返されることです。文字列リテラルは不変で一定であるため、これは文字列リテラルにも当てはまります。したがって、効率のために、各リテラルは 1 回だけ割り当てられます。
実際のところ
NSString * a = @"Hello";
NSString * b = @"Hello";
NSLog(@"%@ %p", a, a); // Hello 0x1f4958
NSLog(@"%@ %p", b, b); // Hello 0x1f4958
元の答え
と訳されますので、
message = [[NSString alloc] initWithUTF8String:"Hello"]];
要するに
message = objc_msgSend(objc_msgSend(objc_getClass("NSString"), @selector(alloc)), @selector(initWithUTF8String:), "Hello");
署名を見てみましょうobjc_msgSend
id objc_msgSend(id theReceiver, SEL theSelector, ...)
メソッドが型を返すことがわかりますid
。これは、Objective-C ではオブジェクト型です。しかし、id
実際にはどのように定義されているのでしょうか?
typedef struct objc_object {
Class isa;
} *id;
id
構造体へのポインタとして定義されていますobjc_object
。
したがって、最終的@"string"
に は、オブジェクト (つまり、objc_object
必要に応じて構造体) へのポインターを生成する関数呼び出しに変換されます。これは、まさに に割り当てる必要があるものですmessage
。
つまり、 object ではなくポインターを割り当てます。
最後の概念をより明確にするために、これを考慮してください
NSMutableString * a = [NSMutableString stringWithString:@"hello"];
NSMutableString * b = a;
[a setString:@"hola"];
NSLog(@"%@", a); // "hola"
NSLog(@"%@", b); // "hola"
オブジェクトを割り当てb
ていた場合、 は のコピーでa
あり、 をさらに変更しa
ても影響はありませんb
。
代わりに、ヒープ内の同じオブジェクトへの 2 つのポインターが得a
られます。b