目次
1 -- ユニバーサルリファレンス
1-1--ユニバーサルリファレンスの実現
ユニバーサル参照は、任意のタイプのパラメータを渡すことができ、パラメータのタイプを自動的に推測します。ユニバーサル参照の 2 つの実装は次のとおりです。
// 基于模板实现
template <typename T>
void f(T&& v){
}
// 基于auto实现
auto && v2 = v1;
1-2--汎用参照と右辺値参照の違い
上記の 2 つの方法を使用してユニバーサル参照を実装する (型推論が必要) のとは異なり (C++ 入門書では、テンプレートに基づくユニバーサル参照もテンプレート型パラメータの右辺値参照として参照します)、平たく言えば、右辺値参照の型は決定的です。たとえば、次は明確な型を持つ右辺値参照です。
int &&
char &&
std::string &&
右辺値参照自体は左辺値ですが、バインドできるのは右辺値のみです。
ユニバーサル参照は、lvalues、rvalues、さらには const オブジェクトと非 const オブジェクトをバインドできます。
2--参照折り方
上記のユニバーサル参照のテンプレート実装では、異なる型 T が渡されると、参照の折りたたみが頻繁に発生します。渡されたパラメータが参照の場合、テンプレートによって推論された型 T が参照への参照になり、その後、参照が発生します。折り畳み;
ユニバーサル参照のテンプレート実装では、参照の折りたたみのルールは次のとおりです。
① 渡されたパラメータが左辺値の場合、テンプレートによって推論される型 T は左辺値参照になります。
② 渡されたパラメータがリテラル値の場合、テンプレートによって推論された型 T がリテラル値の型になります。
③ すべての場合(ポイント④で説明した 1 つの例外)、参照の折りたたみの結果は通常の左辺値参照型になります。
④ ただし、参照の畳み込みの対象が右辺値参照の場合、参照の畳み込みの結果は右辺値参照型になります。
// 基于模板实现
template <typename T>
void f(T&& v){
}
int x = 1;
f(x); // x是一个左值,则 T 的推断结果是左值引用: int &
f(1); // 1是一个字面值,则 T 的推断结果是字面值的类型: int
int&& y = 1;
f(y); // y是一个右值引用,则 T 的推断结果是: int, T && 等价于 int &&;
// 对于一个给定的类型 X
X& &, X& &&, X&& & 都会折叠成X&,
即int& &, int& &&, int&& & 都会折叠成(等价于)int&
类型X&& && 则会折叠成 X&&,
即 int&& && 会折叠成(等价于)右值引用: int&&