0

このトピックに関するいくつかの議論を見つけましたが、それは私の現在の理解レベルを超えていました. Kochan の「Objective-C、4e でのプログラミング」を読んでいて、NSString オブジェクトに関するセクションにいます。まず、私が遊んでいるコードで、質問をすることができます:

NSString *strA = @"StringA";
NSString *strB = @"StringB";
NSLog(@"Value of strA: %@",strA);
NSLog(@"Value of strB: %@",strB);

strB = strA; // strB should point to strA's memory location
NSLog(@"New value of strB: %@",strB); //correctly logs as "StringA"
strA = @"StringA has been changed.";
NSLog(@"New value of strB: %@",strB); //logs as "StringA" still
NSLog(@"New value of strA: %@",strA); //correctly logs as "StringA has been changed"

私の理解では、strB = strA と言うことは、strB が strA のメモリ位置を指していることを意味するため、strA への変更はすべて strB にも適用されます。ただし、これは起こりません。Kochanはそれが想定されていると言い、それを回避するには使用することを提案します

strB = [NSString stringWithString: strA];

私が見る限り、どちらの方法でも機能します。strB = strA と言ってから strA を変更しても、strB は受け取った値 (変更する前の strA の値) を保持しています。

これは NSString が不変であることに起因するのではないかと思っていましたが、そうであれば、実際に初期化後に str1 と str2 の値を変更できるのはなぜですか? ここで何が欠けていますか?ありがとう。

4

4 に答える 4

3

あたかもこれに対する十分な答えをまだ持っていないかのように...

コード例で何が起こっているかを理解するには、1 つまたは 3 つの図が役立つと思います。

まず、あなたのコードはこれを行います:

NSString *strA = @"StringA";
NSString *strB = @"StringB";

これにより、アプリのメモリは次のようになります。

メモリダイアグラム 1

左側にはローカル変数strAstrB. それらはメモリ内のオブジェクトへの単なるポインタです。

真ん中は文字列オブジェクトです。これらはソース コードに表示されるため、コンパイラによってアプリで事前に作成されます。

右側は文字列オブジェクトの実際の文字です。これらも、コンパイラによってアプリで事前に作成されます。

次に、あなたのコードはこれを行います:

strB = strA;

アプリのメモリは次のようになります。

メモリダイアグラム 2

ローカル変数strBが変更されましたが、オブジェクトと文字は変更されていないことに注意してください。

最後に、あなたのコードはこれを行います:

strA = @"StringA has been changed.";

これにより、アプリのメモリは次のようになります。

メモリーダイアグラム 3

ローカル変数strAは変更されましたが、オブジェクトと文字はまだ変更されていません。

于 2012-07-18T21:01:41.910 に答える
1

私の理解では、strB = strA と言うことは、strB が strA のメモリ位置を指していることを意味するため、strA への変更はすべて strB にも適用されます。

はい、どちらも同じオブジェクトを指しているstrBと言った方が明確かもしれませんが。strA

strB = strA と言ってから strA を変更しても、strB は受け取った値 (変更する前の strA の値) を保持しています。

を変更するstrAと、必然strA的に別の文字列を指すことになります。NSString は不変であるため、変更することはできません。置き換えることしかできません。したがって、次のようなことを言うと:

strA = [strA stringByAppendingString:@"foo"];

その後strA、元の文字列を指しなくなります。strBもちろん、まだ元のオブジェクトを指しており、そのオブジェクトは変更されていないため、 が指す文字列と が指す文字列strAstrB異なるオブジェクトです。

ここで何が欠けていますか?

割り当てを行うと新しいオブジェクトが作成されると考えていると思いますstrB = strA;が、実際にはそのステートメントの後に両方のポインターが同じオブジェクトを指します。strA新しいオブジェクトが作成されるのは、「変更」したときです。

さて、もちろん変更可能な可変文字列について話している場合は、状況が異なります。すると、次のような状況になります。

NSMutableString *mstrA = [@"foo" mutableCopy];
NSMutableString *mstrB = mstrA;     // now mstrB points to the same object as mstrA
[mstrA appendString:@"bar"];
NSLog(@"%@", mstrB);                // will log @"foobar" because the string actually changed
于 2012-07-18T20:35:37.917 に答える
0

私の理解では、strB = strA と言うことは、strB が strA のメモリ位置を指していることを意味するため、strA への変更はすべて strB にも適用されます。

strA のメモリ位置の変更 -- はい。同じ場所へのまったく無関係なポインターへの変更。現在は別の場所を指しています。いいえ。

于 2012-07-18T20:34:16.023 に答える
0

ここで何が起こっているかを考えるには 2 つの方法があります。1 つは、もう少し低レベルですが、pointerと呼ばれる構造を扱っていることです。intポインタは、変数が整数値を保持するのとまったく同じ方法で、メモリ アドレスを保持します。intを別のに割り当てた場合int、最初のものを変更しても、2 番目のものは変更されません。

int i1 = 10;
int i2 = i1;
i1 = 600;    // i2 still 10

同じことがポインターにも当てはまります。

それを考えるもう1つの(おそらくより生産的な)方法は、strAstrBが実際にオブジェクトの名前であることです。オブジェクトをある名前から別の名前に割り当てると、両方の名前が同じオブジェクトを保持します。メモリ管理とオブジェクトの有効期間の問題は別として、1 つの名前を別のオブジェクトに再割り当てすることができ、もう 1 つの名前は引き続き元のオブジェクトを指します。

于 2012-07-18T20:42:09.963 に答える