6

ARC(自動参照カウント)に移行していますが、このドキュメントは非常に役に立ちました:ARCリリースノートへの移行。それは言う:

ブロックはARCでどのように機能しますか?

リターンなどのARCモードでブロックをスタックに渡すと、ブロックは「正常に機能」します。もうBlockCopyを呼び出す必要はありません。スタックをarrayWithObjects:および保持を行う他のメソッドに「ダウン」させる場合は、[^{}copy]を使用する必要があります。

誰かがこれについて少し詳しく説明したり、いくつかの例を挙げたりできますか?ARCがよりスマートに処理するようになったため、宣言されたスコープ外でブロックが使用された場合でも、通常は[ブロックコピー]を実行する必要がないことを理解しましたが、必要なときにコピーする必要があります。ブロックを保持する関数にブロックを渡します。これは正しいです?

実際、少し実験してみましたが、これまでのところ、コピーせずにブロックを配列に渡しても問題ないようです。ありがとう!

4

1 に答える 1

14

MRC(手動参照カウント)の観点から問題を考えてみましょう。関数からスタックブロックを返す場合、そのコピーを返すことは常に正しいことです[[ copy] autorelease](通常はを使用して)。これは、スタックブロックの存続期間が、終了する関数呼び出しであるためです。したがって、返されたポインタが戻った後に有効なブロックを指すようにするには、もちろんヒープコピーを返す必要があります。

ただし、関数またはメソッドへの引数としてブロックを渡す場合はどうでしょうか。あなたはそれのコピーを渡す必要がありますか?もう少し複雑です。後で関数呼び出しよりも長持ちする場所(インスタンス変数やグローバル変数など)で使用するためにブロックを保存する必要がある場合は、ブロックのコピーを保存する必要があることを私たちは知っています。しかし、これがいつ真であるか(そして、真である場合、どの関数(呼び出し元/呼び出し先)がそれをコピーする責任があるか)をどのように知ることができますか?

一般に、パラメーターがブロックタイプの関数またはメソッドに渡す場合、コピーする必要はありません。これは、ブロックパラメーターを受け取る関数として、その関数が必要に応じてコピーする責任があるためです。後で使用するために保管してください。

しかし、パラメーターが非ブロックタイプ(のようなid)である関数またはメソッドにブロックを渡すのはどうですか?その場合、その関数は引数がブロックであることを認識しないため、後で使用するためにオブジェクトを保存する必要がある場合にのみオブジェクトを保持し、コピーはしません。この場合、関数またはメソッドが後でオブジェクトを格納することがわかっている場合(たとえば、を使用して-[NSMutableArray addObject:])、ブロックのコピーを渡す必要があります。常にコピーを渡す必要がありますか?必ずしも。関数またはメソッドが後でブロックを保存しないことがわかっている場合(たとえば、オブジェクトを印刷するだけの場合)、ブロックのコピーを作成するのは非効率的です。

ARCでは、コンパイラは可能な限り多くのことを実行しようとします。したがって、スタックブロックを返す(「渡す」)場合、コンパイラはコピーを返すことが常に正しいことであると認識しているため、暗黙的にそれを行います。だから、もう自分でやる必要はありません。

ただし、ブロックをメソッドまたは関数に渡す(「渡す」)場合、コピーが必要かどうかを自動的に判断できるとは限らず、余分なコピーは非効率的である可能性があるため、コンパイラは自動的に何もしません。 ; そして、プログラマーはそれを理解する必要があります。

コンパイラの最近のバージョンでは、ARCは私が思っていたより多くの状況でブロックをコピーすることに気づきました。そのため、注意を怠るために、ARCの実装をほぼ常にブロックをコピーするように変更した可能性があります。彼らは、パフォーマンスコストはそれほど重要ではないと信じていました。addObject:したがって、明示的にコピーせずにブロックを直接に渡すことで機能する可能性があります。しかし、これはARCの場合は必ずしもそうではなく、この言語での保証はなく、この動作が将来も続くと私は信じています。

于 2013-02-02T03:13:30.120 に答える