80

私が SO で目にするほぼすべての投稿で、 a を含む、人々は aを値std::initializer_listで渡す傾向があります。std::initializer_listこの記事によると:

https://web.archive.org/web/20120707045924/cpp-next.com/archive/2009/08/want-speed-pass-by-value/

渡されたオブジェクトのコピーを作成したい場合は、値で渡す必要があります。しかし、 a をコピーするのstd::initializer_listは得策ではありません。

をコピーしstd::initializer_listても、基になるオブジェクトはコピーされません。元の初期化子リスト オブジェクトの有効期間が終了した後、基になる配列が存在することは保証されません。

では、なぜ it のインスタンスは、たとえば ではなく、値によって渡されることが多いのconst&ですか?

4

2 に答える 2

70

安いので値渡しです。std::initializer_listはシン ラッパーであり、1 組のポインターとして実装される可能性が最も高いため、コピーは (ほぼ) 参照渡しと同じくらい安価です。さらに、実際にはコピーを実行しているのではなく、(通常は)移動を実行しています。これは、ほとんどの場合、いずれにしても引数が一時的なものから構築されるためです。ただし、これはパフォーマンスに違いはありません。2 つのポインターを移動することは、それらをコピーすることと同じくらいコストがかかります。

一方、コピーの要素へのアクセスは、 1 つの追加の逆参照 (参照の逆参照) を回避するため、高速になる場合があります。

于 2013-07-23T07:05:39.603 に答える
15

おそらく同じ理由で、イテレータはほとんど常に値渡しされます。イテレータのコピーは「安価」と見なされます。の場合、initializer_listほとんどのインスタンスが自明なデストラクタを持つ一時的なものになるという事実もあるため、コンパイラは関数の引数を配置する場所にコピーなしで直接それらを構築できます。最後に、反復子と同様に、呼び出された関数が値を変更する可能性が高いという事実があります。つまり、const への参照によって渡された場合は、値をローカルにコピーする必要があります。

編集:

一般化すると、標準ライブラリは一般に、反復子、initializer_lists、および機能オブジェクトを値で渡す方がよいと想定しています。結果として、あなたが設計するイテレーター、イテレーターリスト、または機能オブジェクトは、コピーするのが安価であることを確認する必要があり、独自のコードでは、コピーするのが安価であると想定する必要があります。const への参照を使用するタイミングと値を使用するタイミングに関する従来のルールは、おそらくこれを反映するように変更する必要があります。

反復子、initializer_lists、または機能オブジェクト以外のクラス型には、const への参照渡しを使用します。それ以外の場合は、値渡しを使用してください。

于 2013-07-23T08:09:07.590 に答える