保持カウントが 5 の NSString などのオブジェクトがあるとします。copy を呼び出すと、オブジェクトの新しいコピーが取得されます。この新しいオブジェクトには、元のオブジェクトの保持カウントがありますか?
6 に答える
場合によります。copy
の便利な方法でcopyWithZone:
あり、「NSCopying Protocol Reference」には次のように記載されています。
このプロトコルを実装するためのオプションは次のとおりです。
- copyWithZone: を継承しないクラスの
NSCopying
usingalloc
とin を実装します。init...
- 動作継承時
NSCopying
にスーパークラスを呼び出して実装する。スーパークラスの実装で関数を使用する可能性がある場合は、保持されたオブジェクトのポインター インスタンス変数に明示的な割り当てを行います。copyWithZone:
NSCopying
NSCopyObject
NSCopying
クラスとその内容が不変の場合、新しいコピーを作成するのではなく、オリジナルを保持して実装します。
(すべてのフィードバックを受けて、次の 2 つのステートメントを修正しました。)
たとえば、NSString
は不変オブジェクトでありcopy
、オブジェクトを保持し、同じオブジェクトへのポインターを返すだけです。オブジェクトを保持すると、保持カウントが増加する可能性がありますが、必ずしもそうとは限りません (文字列リテラルの場合と同様)。
をコピーするNSMutableString
と、おそらく新しいオブジェクトが作成され、それが返されます。新しいオブジェクトには、元のオブジェクトとは独立した独自の保持カウントがあります。
しかし、違いを気にする必要はありません。手動参照カウントで
は、所有していて最終的に解放copy
する必要があるオブジェクトを返します。ARC では、コンパイラが自動的にそれを処理します。
copy
オブジェクトのセマンティック [浅い] コピー(1) であるオブジェクトを返します。copy
メソッドが返すのは実装の詳細です。同じオブジェクトを返す場合もあれば、同じクラスの別のインスタンスを返す場合もあれば、別のクラスのインスタンスを返す場合もあります。
関係ない。
重要なのは、返されたオブジェクトが手動保持/解放の下で、+1 の保持カウントを持つことです。1ではなく+1です。実際には 1、42、981、または -1 の可能性があります。関係ない。
重要なのは、オブジェクトを放棄してシステムに戻したい場合は、release
またはどこかで保持するバランスを取る必要があるということだけです。autorelease
これにより、実際に割り当てが解除されることはありません。これは実装の詳細に関係ありません (とにかく最適化の時間まで)。
(1)セマンティック [浅い] コピーとは、返されるオブジェクトが有効な浅いコピーであることを意味します。コピーされたオブジェクト内に含まれる状態 (オブジェクト内に含まれるオブジェクト内ではなく、浅い部分) は、元のオブジェクトの状態が変化しても変化しません。変更可能なオブジェクトの場合copy
、元の状態を格納できる何らかのオブジェクト (おそらく不変のバリアント クラス) の新しいインスタンスを実際に作成する必要があります。
不変オブジェクトの場合、copy
メソッドは単純に として実装される場合がありますreturn [self retain];
。または、静的な NSStrings ( NSCFStrings
)の場合はreturn self;
、そのような文字列に対して保持/解放/自動解放がノーオペレーションであるためです。
いいえ、新しく初期化されたオブジェクトと同様に、コピーされたオブジェクトの保持カウントは 1 になります。
詳細を知りたい場合は、メモリ管理ガイドを読むことを強くお勧めします。
iOS 開発に慣れていない場合は、最初にiOS アプリ プログラミング ガイドを読む必要があります。時間を有効に活用できます。
これを iOS 固有としてタグ付けしていないことに気付きました。Mac 用にコーディングしている場合は、Objective-C を使用したプログラミングガイドの方が適している可能性があります。
この問題を本当に理解するには、保持数の観点からではなく、ポインターの所有権の観点から考えてください (ARC のように)。
オブジェクトの "retain count" が 5 の場合、それはどこかにある 5 つのコードがそれぞれそのメモリ アドレスへの (強力な) ポインタを保持していることを意味します。copy
そのオブジェクトの場合、新しくコピーされたオブジェクトのアドレスへのポインターを取得します。残りの 5 つのコードは、まだ元のオブジェクトを指しています。新しいオブジェクトを指すコードは 1 つしかないため、その「保持カウント」は 1 です。
他の回答で述べたように、メモリ管理ガイドはこれをすべて明確にするのに役立ちます。
「retain count」を引用符で囲んだのはなぜですか? これは一般的な概念としてのみ役立つため、retainCount
直接使用しないでください。使用しないと、@bbum から連絡があります。
Objective-C にオブジェクトをコピーするように要求すると、Objective-C はいくつかの巧妙なトリックを実行します。その結果、保持カウントは、本来あるべきものとは異なる場合があります。
保持カウント n を持つオブジェクト ポインター x があり、オブジェクト ポインター y を返す copy メソッドを呼び出すとします。
NSObject* x = ...;
NSObject* y = [x copy];
次に、xn 回解放し、y を 1 回解放すると、すべてのオブジェクトがなくなるという規則があります。通常、これは x を変更せずに残し、ya の保持カウントを 1 にすることで実現されます。
ただし、x が不変オブジェクトを指している場合、Objective-C はコピーを実行する必要がないと判断する場合があります。結果は y = x です。それでも、上記のルールは適用されます: xn 回と y を 1 回解放すると (それらが同じオブジェクトであっても)、関係するすべてのオブジェクトが解放されます。これは、保持カウントが +1 の x を返す copy メソッドによって実現されます。
NSMutableArray のような可変オブジェクトのコピーは新しいコピーを作成し、保持カウントは 1 になりますが、NSArray のような不変オブジェクトのコピーは同じ参照を指し、保持カウントを 1 増やします。