7

例では

NSString *message = @"Hello";
message = @"World";

*message = @"World";メッセージが単なるポインターである場合、メッセージにあるものはすべて文字列またはCのように等しいと明示的に言う必要がないのはなぜですか?

4

1 に答える 1

14

免責事項

以下の説明は、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

于 2013-04-09T17:47:52.357 に答える