- void setter(type val) { var = val; }
- void setter(const type& val) { var = val; }
- void setter(const type& val) { var = val; }
void setter(type&& val) { var = std::move(val); } - template<typename T>
void setter(T&& val)
{ var = std::forward<T>(val); } - void setter(type val) { var = std::move(val); }
結論から書くと、
- intやfloatなら1で
- std::stringなどmoveが軽く、コピーできるなら5で
- 派生クラスなどコピーできないなら、2で
- 自前クラスでmoveが重く、コピーもできて、
どうしても高速化したいなら、3で
4は3を1行で書いてるだけなので、普段は使いにくいかと。
3で全部書くから5は使わないという方針もありですが、
同じ関数を何個も書くのは資源の無駄ですし、
5を取り入れるのはいい考えだと思います。
最後に、それぞれの処理内容を比べてみましょう。
- lvalueだと関数呼び出し時のコピー1回、代入時のコピー1回
rvalueだと関数呼び出し時のコピーは省略、代入時のコピー1回 - lvalueだと関数呼び出しは参照渡し、代入時のコピー1回
rvalueだと関数呼び出し時は参照渡し、代入時のコピー1回 - lvalueだと関数呼び出しは参照渡し、代入時のコピー1回
rvalueだと関数呼び出しは参照渡し、代入時のムーブ1回 - lvalueだと関数呼び出しは参照渡し、代入時のコピー1回
rvalueだと関数呼び出しは参照渡し、代入時のムーブ1回 - lvalueだと関数呼び出し時のコピー1回、代入時のムーブ1回
rvalueだと関数呼び出し時のコピーは省略、代入時のムーブ1回
“setName(std::string("str"));”のstd::stringのコンストラクタ部分は
数えていません。
ムーブができるようになったので、5のコスト低下が顕著です。
また、5の場合内部でメモリ確保をしないので、noexceptionが
つけれます。そんな感じで5はなかなかいい選択肢になってます。
0 件のコメント:
コメントを投稿