1

たとえば、私たちは常にこのように書きます1:

-(NSObject*)giveMeAnObject
{
    return [[[NSObject alloc] init] autorelease];
}

-(void)useObject
{
    NSObject *object = [self giveMeAnObject];
    //use that object
}

しかし、なぜ私たちはこのように書いてみませんか2:

-(NSObject*)giveMeAnObject
{
    return [[NSObject alloc] init];
}

-(void)useObject
{
    NSObject *object = [self giveMeAnObject];
    //use that object
    [object release];
}

Cocoa SDKは方法1のようなことをします。それが、私たち全員が方法1を使用する理由だと思います。これは、コーディング規約になっています。しかし、慣例が方法2の場合、パフォーマンスの向上はほとんど得られないと思います。

では、コーディング規約を除いて、方法2ではなく方法1を使用する理由は他にありますか?

4

3 に答える 3

4

自動解放されたオブジェクトを返すことは、抽象化の一種です -- 開発者にとって便利なので、返されたオブジェクトの参照カウントについてそれほど考える必要はありません -- その結果、特定のカテゴリのバグが少なくなります (ただし、また、自動解放プールがバグや複雑さの新しいカテゴリを導入すると言うこともできます)。はい、パフォーマンスが低下する可能性がありますが、クライアントコードを本当に簡素化できます。また、参照操作を行う必要がない場合に、抽象化された最適化として使用することもできます。オブジェクトが返されたもののインスタンスを保持し、保持またはコピーを行う必要がない場合を考慮してください。ステートメントの連鎖は多用される可能性がありますが、この方法はステートメントの連鎖にも便利です。

また、参照カウント エラーを判断する静的アナライザーは、これらのライブラリやプログラムの一部では比較的新しいものです。自動解放プールは、ARC および objc オブジェクトの参照カウントの静的分析に何年も先行していました。これらのツールを使用すると、参照カウントが正しいことを確認することがはるかに簡単になりました。多くのバグを検出できます。

もちろん、ARC では、自動解放されたオブジェクトを返すシンプルさを好むと、その多くが変わります。

統一所有権セマンティクスを使用すると、プログラムも簡素化されます。抽象セレクターまたはセレクターのコレクションが常に同じセマンティクスを使用して返される場合、いくつかの一般的なフォームを本当に単純化できます。たとえば、渡されたセレクターのセットperformSelector:が異なる所有権のセマンティクスを持っている場合、多くの複雑さが追加されます。そのため、返却時に所有権を統一することで、より「一般的な」実装のいくつかを本当に簡素化できます。

パフォーマンス: 参照カウント操作 (保持/解放) は、特に下位レベルでの作業に慣れている場合は、かなり重くなる可能性があります。ただし、現在の自動解放プールの実装は非常に高速です。それらは最近更新され、以前よりも高速になりました。コンパイラとランタイムは、いくつかの特別なショートカットを使用して、これらのコストを低く抑えます。また、特にモバイル デバイスでは、自動解放プールのサイズを小さくしておくことをお勧めします。自動解放プールの作成は非常に高速です。実際には、自動解放操作自体からゼロから数パーセントの増加が見られる場合があります (つまり、自動解放操作よりもはるかに短い時間しかかかりません)。objc_msgSend+バリアント)。いくつかのテストは、わずかに速く実行されました。これは、多くの人が得られる最適化ではありません。典型的な状況では簡単に達成できるものではありません。実際のプログラムでそのような変更の影響と局所性を測定することは、実際には比較的困難です.bbumが以下の変更について言及した後に私が行ったいくつかのテストに基づいています. そのため、テストの範囲は限定されていましたが、MRC と ARC の方が優れている/高速であるように見えます。

したがって、これの多くは、独自の参照カウント操作を実行している場合に想定する責任のレベルに帰着します。ほとんどの人にとって、書き方を変えるべきではありません。最新のシステムで実行している場合、メモリの問題のローカライズ、より決定論的なオブジェクトの破壊、およびより予測可能なヒープ サイズが、「所有」(+1) 参照カウントを返すことを好む主な理由だと思います。それでも、多くの場合、ランタイムとコンパイラはこれを削減するために機能します (bbum の回答 +1 を参照)。自動解放プールはほぼ同じくらい高速ですが、現時点ではこれ以上使用するつもりはありません.

于 2012-09-02T04:53:49.300 に答える
3

パフォーマンスの利点を測定しましたか? autoreleaseCF スタイルの caller-must-release と比較して、測定可能なパフォーマンスへの影響がある定量化可能なケースはありますか?

そうでない場合は、議論の余地があります。もしそうなら、autorelease とそうでないものをはるかに凌駕する体系的なアーキテクチャの問題があるに違いありません。

いずれにせよ、ARC を採用すれば、自動解放の「コスト」は最小限に抑えられます。コンパイラとランタイムは、メソッド呼び出し全体で自動解放を実際に最適化できます。

于 2012-09-02T05:56:45.420 に答える
0

主な理由は3つあります。

  1. それは所有権を取得するという概念を課します。
  2. ダングリングポインタの問題を排除します。
  3. ローカル自動リリースプールで作成されたオブジェクトを返すため、パフォーマンスが向上します。
于 2012-09-02T12:20:31.870 に答える