0

私は次の比較方法を持っています。このメソッドは比較し、差分結果を返します。

結果リストが (テンポラルおよび代入に) コピーされる時間を最小限に抑えたいと考えています。

これを行う 1 つの方法は、結果に追加の参照引数を追加することですが、utils 関数が閉じている (値を変更しない) のが好きなので、これを避けることを好みます。

代入で const& を使用することで、1 つのコピーを回避できます。

const& list<uint32> diff = getDiffNewElements (...)

、テンポラルへのローカルコピーを回避する方法にもなりますか?

diff メソッド:

list<uint32> getDiffNewElements(const list<Row>& src ,const list<Row>& dst) {
    list<uint32> result;

        ... Do Some compare

        return result;
}
4

2 に答える 2

2

提示するコードには、2 つのコピーが存在する可能性があります。result変数から返されたオブジェクトまでの関数内の 1 つ。機能の複雑さが許せば、NRVO が対応します。単一の return ステートメントがあるように見える場合、コンパイラはそのコピーを省略します (コンパイラ フラグでそれを無効にしておらず、何らかの最適化レベルが有効になっていると仮定します)。

2 番目の潜在的なコピーは、戻り値から最終ストレージまでの呼び出し元にあります。そのコピーはほとんどの場合、コンパイラによって省略されます。ここでは、NRVO の場合よりもさらに簡単に行うことができます。呼び出し規約 (私が知っているすべての呼び出し規約) は、呼び出し元が返されたオブジェクト用のスペースを予約することを決定します。その場所への隠しポインタを関数に渡します。関数は、そのポインターを最初のコピーの宛先として使用します。

関数T f()は に変換されvoid f( uninitialized<T>* __ret )( のようなものはありませuninitialized<>んが、ご容赦ください)、関数の実装では、returnステートメントにコピーするときにそのポインターを宛先として使用します。呼び出し元のサイトで、コンパイラがある場合は、それを次T a = f();のように変換しますT a/*no construction here*/; f(&a);

質問には、あなたが過去に誤解を招いたことを示す興味深いコードがあります: const list<uint32>& diff = getDiffNewElements(...). ( のように) 値を直接格納するのではなく、参照を使用しても、list<uint32> diff = getDiffNewElements(...)作成されるコピーの数にはまったく影響しません。返されたオブジェクトにコピーgetDiffNewElements(またはコピーを省略) する必要があり、そのオブジェクトは呼び出し元のスコープ内にあります。const 参照を取得することで、そのオブジェクトに直接名前を付けるのではなく、スコープ内の名前のないオブジェクトとして保持し、参照のみを使用することをコンパイラーに伝えます。意味的には、次のように変換できます。

T __unnamed = getDiffNewElements(...);  // this copy can be elided
T const& diff = __unnamed;

コンパイラは無料であり、おそらく余分なスペースを必要とせずに識別子diffをエイリアスとして使用して参照を最適化する__unnamedため、一般的には代替よりも悪くはありませんが、コードはわずかに複雑であり、利点はありませんまったく。

昔、時間があったときにブログを始めて、値セマンティクス、(N)RVO、コピー省略に関する記事をいくつか書きました。見てみるといいかもしれません。

于 2012-11-01T12:02:06.267 に答える
0

あなたは間違った方向を見ています。最新のコンパイラはRVOを実行getDiffNewElementsするため、メソッドは不要なコピーを作成しません(コメントで指摘されましたが、コンパイラがRVOを実行しない場合、それについてできることは何もありません。助けにはなりません)。この関数を最適化する方法は、の代わりにreturn を使用することです。これは、新しい要素を呼び出すたびにメモリ割り当てを呼び出して回避できるためです。デフォルトのアロケータでメモリを事前に割り当てず、それを行う方法がありません。const&vectorlistreservevectorpush_backlistreserve

于 2012-11-01T11:18:57.647 に答える