void func()
{
Thing t;
work_on(t); // <--- POINT 1
work_on(move(t)); // <--- POINT 2
work_on(Thing()); // <--- POINT 3
}
t
POINT 1の式はlvalue
.
move(t)
POINT 2の表現はxvalue
.
POINT 3の式Thing()
は aprvalue
です。
式のこの値カテゴリに基づいて、オーバーロードされたセットから最適な実行可能な関数が選択されます。
使用可能な 2 つの機能が次のとおりであるとします。
work_on(const Thing&); // lvalue reference version
work_on(Thing&&); // rvalue reference version
Anlvalue
は左辺値参照バージョンを選択し、右辺値参照バージョンにバインドすることはありません。
xvalue
or prvalue
(まとめて と呼ばれる)rvalues
はどちらかに有効にバインドされますが、使用可能な場合はより適切な一致として右辺値参照バージョンを選択します。
の 2 つのバージョンの実装内ではwork_on
、パラメータはほとんど同じです。これの目的は、右辺値参照バージョンが引数を変更または移動するものであると想定できるようにすることです。そのため、その引数で移動コンストラクターを呼び出すことができますが、左辺値参照バージョンはそうすべきではありません。
したがって、パラメーターを追加する必要があるvector<Thing> V
ものがあるとします。work_on
void work_on(Thing&& t)
{
V.push_back(move(t));
}
void work_on(const Thing& t)
{
V.push_back(t);
}
std::vector::push_back
と同様の方法でオーバーロードされ、work_on
同様のオーバーロード解決が行われます。の 2 つの異なる実装内でpush_back
、右辺値参照バージョンは move コンストラクターを呼び出して値をその配列にプッシュし、場合によっては を破棄しt
ます。左辺値参照バージョンはコピー コンストラクターを呼び出し、t
そのまま残します。
この言語メカニズムの主な目的は、変数 (lvalues)、意図的にマークされた期限切れの値 (xvalues)、および一時変数 (prvalues) を追跡することです。これにより、それらのリソースをいつ安全に再利用 (移動) できるか、いつコピーできるかがわかります。彼ら。