明確にするために:値渡しの答えは間違っていません。string&&
しかし、1 つの詳細を除いて、どちらもオーバーロードを追加する最初の推測ではありません。
追加:
X (std::string&& s) : S(std::move(s)) { }
つまり、への右辺値参照の宣言された型がありますが、初期化に使用される式は型の左辺値式であるmove
ため、がまだ必要です。s
string
s
S
string
実際、最初に提案したソリューション (移動を追加したもの) は、値渡しのソリューションよりもわずかに高速です。でもどちらも正しい。値渡しソリューションは、lvalue および xvalue 引数を X のコンストラクターに渡すときに、string の move コンストラクターを余分に呼び出します。
左辺値引数の場合、とにかくコピーが作成され、文字列のコピー コンストラクターは、文字列の移動コンストラクターよりもはるかにコストがかかる可能性があります (短い文字列バッファー内に収まる文字列を除きます。この場合、移動とコピーはほぼ同じです)。速度)。
xvalue 引数 (xvalue は に渡された左辺値std::move
) の場合、値渡しソリューションでは、1 つではなく 2 つの移動構成が必要です。したがって、右辺値参照によるパス ソリューションの 2 倍のコストがかかります。しかし、それでも非常に高速です。
この投稿のポイントは、明確にすることです。値渡しは許容できるソリューションです。しかし、それが唯一の受け入れられる解決策ではありません。pass-by-rvalue-ref を使用したオーバーロードは高速ですが、必要なオーバーロードの数が、引数 N の数が増えるにつれて 2^N にスケーリングされるという欠点があります。