c++11の主要なtopicであるムーブセマンティクスは非常に多くの方が解説されいます。
しかし初学者が一つの記事で理解できるようにはなっていないのが現状です。
そこで以下に順番に読むとわかりやすいリンクを挙げていきます。
Return value optimization : Wikipedia
先に知っておく方が良い基礎知識。
C++11は関係ありません。
# include <iostream>
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
(Wikipediaより転載)の挙動に自信が無い人は必読です。
とはいえ最適化は標準規格ではないので、実行されるかどうかはコンパイラに依るし、
複雑なコードになれば最適化が阻害される可能性がある。
本当は怖くないムーブセマンティクス : yohhoyの日記(別館)
yohhoy氏による記事です。
基本的な事を丁寧に解説してある、非常に良い記事です。
とりあえずstd::move
ってよくわからんって人は是非とも読みましょう。
本文中にある要約を転載します
- 「ムーブセマンティクス」は昔からあるイディオムですが、C++11からはコンパイラもムーブセマンティクスを認識できるようになりました。
- C++11標準ライブラリ提供のクラスは、「最適化されたコピー」または「所有権の移動」としてのムーブに対応しました。
- コピー代入シンタックス
u = t
とムーブ代入シンタックスu = std::move(t)
を区別し、用途に応じて使い分けましょう。- ムーブを利用するだけなら、「右辺値参照」を気にする必要はありません。関数の引数/戻り値では「値渡し」スタイルを使いましょう。
(転載ここまで)
C++0x 標準ライブラリ完全解説 〜 No.02 std::move, : 野良C++erの雑記帳
gintenlabo氏の記事。
こちらも同様にstd::move
の基本事項を説明しています。
ムーブの説明自体はyohhoyさんのものの方がわかりやすいと思いますが、
こちらでは具体的に必要な場面の説明が多数挙げられています。
参照渡し or 値渡し? : yohhoyの日記
結局どうやって関数を書けばいいんだってばよ!?
という方向け。
本文中にある要約を転載します
- C++03:通常は
const T&
でよい。ただしT型が小さくtrivialな場合はT
の方が低コスト。(intなどの組込み型ではconst int&
よりも単にint
の方が低コスト。)- C++11:コピー操作よりも低コストなムーブ操作があり、かつ実引数が常にlvalueという使われ方でなければ、T による値渡しが有効。
- C++11:const lvalue参照渡し(
const T&
), rvalue参照渡し(T&&
)の2種類をオーバーロード関数として提供すると、ムーブまたはコピー 1回 まで削減される。- 「常に値渡しを使うこと」や「値渡しは禁止」は共に正確でなく、関数インターフェイス設計の問題である。
(転載ここまで)
結局overloadするのが最強という結果になります
C++0x における NRVO : 野良C++erの雑記帳
関数の戻り値でムーブを使う場合の注意事項。
むしろ、ローカル変数 x の型が関数の戻り値の型と異なる場合や、
x がローカル変数ではなく関数の引数だった場合、
あるいは関数呼び出しを挟んでreturn f(x);
と返す場合などは、
明示的にmove
しないと move されないので、
そのような場合にうっかり move を忘れないように、
常に明示的に move するようにするのも、悪くない習慣だとは思います。
同じような記事として
暗黙のmoveとNRVO : joynote break;があります。
(コメントしているのgintenlabo氏だけど)