関数は右辺値または左辺値を返しません。値のカテゴリは式に適用されます。したがって、関数を呼び出す式は、右辺値または左辺値である可能性があります。この場合、関数はオブジェクトを値で返すgetName()
ため、式は右辺値式です。getName
これは §5.2.2/10 からのものです。
関数呼び出しは、結果の型が左辺値参照型または関数型への右辺値参照の場合は左辺値、結果の型がオブジェクト型への右辺値参照の場合は xvalue、それ以外の場合は prvalueです。
関数の結果の型は左辺値または右辺値の参照ではないため、関数呼び出しは prvalue です。prvalue 式は、rvalue 式のサブセットです。
move コンストラクターが使用されます (省略されている場合を除きます)。これgetName()
は が右辺値であるため、右辺値参照を受け取る のコンストラクターがstd::string
引数によりよく一致するためです。move 構築が省略された場合でも、move コンストラクタにアクセスできる必要があることに注意してください。つまり、省略されていなくても、コードはコンパイル可能でなければなりません。
一般に、コピーまたは移動の省略を最適化すると、コピーまたは移動が完全に取り除かれます。もちろん、実際に移動するよりも高速です。動きが省略された場合、文字通り何も起こりません。その移動に対して発行されるコードはありません。コンパイラは、コピー先または移動先の場所にオブジェクトを直接構築することでこれを実現します。
これも同様に最適化できることに注意してください。
string getName () {
std::string str("meme");
return str;
}
string name = getName();
ここでは、2 つの手が省略されます (名前付き戻り値の最適化として一般に知られているものを含みます)。ここで考慮すべき点が 2 つあります。まず、return str;
コピー/移動省略の基準を満たしています (§12.8/31):
コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。
- クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性自動オブジェクト (関数または catch-clause パラメーター以外) の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます
- ...
2 つ目はstr
、左辺値ですが、標準 (§12.8/32) で指定された特別なケースに適合するため、移動されることです。
コピー操作の省略の基準が満たされているか、ソース オブジェクトが関数パラメーターであり、コピーされるオブジェクトが左辺値によって指定されているという事実を除いて満たされる場合、コピーのコンストラクターを選択するためのオーバーロードの解決は次のとおりです。オブジェクトが右辺値によって指定されたかのように最初に実行されます。