ソース関数とシンク関数を作成する場合、移動セマンティクスの恩恵を受けるためにどのシグニチャを使用する必要がありますか。その理由は何ですか。
T source();
sink(T);
// or
T&& source();
sink(T&&);
ソース関数とシンク関数を作成する場合、移動セマンティクスの恩恵を受けるためにどのシグニチャを使用する必要がありますか。その理由は何ですか。
T source();
sink(T);
// or
T&& source();
sink(T&&);
T&& source()
ソースが新しいオブジェクトを作成して返すことを考えると、間違いなくゴミです。関数からローカル変数への参照を返さないでください。このルールは、左辺値参照に常に適用されるのと同じように右辺値参照にも適用されます。
使用sink(T&&)
はむしろ好みの問題です。それほどクリーンで合理化されているようには見えませんが、一方で、関数のシンクの性質をより明確に強調し、コピーされる可能性のあるタイプであっても、移動を必須にします。しかし、とにかくT
コピー不可能なタイプ(のような)であると思われる場合は、少しきれいに見え、とにかくタイプのコピー不可能な性質によって移動が明示的に示されているのでstd::unique_ptr
、私は好みます。sink(T)
しかし、それでもなお、すべての場合において、移動セマンティクスの恩恵を受けることになります。これは、その強みの1つであり、既存のコードにうまく統合されます。したがって、どの署名を持っていても、T t = source();
移動します。それは、コピー可能なタイプの代わりにそれを呼び出すことを妨げるものではありません。コピー可能なタイプは、移動セマンティクスを利用しません。しかし、それはまったく別の問題です。とにかく、適切なときに使用することは、できるだけ早く習得するイディオムでなければならないからです。sink(std::move(t));
sink
sink(T)
sink(t);
sink(std::move(t));
std::move
編集:確かに、sink(T)
効率的に移動できない型(値ベースの実装を使用する型などstd::array
)ではうまく機能しません。これは、(右辺値)参照がおそらく行う場所にコピーが必要になるためです。また、まったく動かない活字の場合でも、動くよりも高速です(ただし、これは無視できるはずです)。しかし、繰り返しになりますが、ソースとシンクは、そもそも値が実装されたタイプではうまく機能しないと思います。そして、この場合T source()
、とにかく、パフォーマンスに関してはそれほど良いアイデアではありません(ただし、T&& source()
上記のように置き換えることはできません)。