move : 移動語意,得到右值型別
forward:型別轉發,能夠識別左值和右值型別
只有兩種形式的參考,左值參考和右值參考,萬能參考不是一種參考型別,它存在于模板的參考折疊情況,但是能夠接受左值和右值
區分左值和右值得一個簡單方式就是能不能取地址
一個右值一旦有名字那么就變成了左值
#include <iostream>
using namespace std;
void process(int & i) {
std::cout << i << " lvalue" << std::endl;
}
void process(int && i) {
std::cout << i << " r value" << std::endl;
}
template<typename T>
void test(T && v) { //這里的&& 表示萬能參考,既能接受左值也能接受右值
process(v);
}
int main() {
int i = 100;
test(i);
test(200);
system("pause");
return 0;
}
上面的運行結果 我們發現 test(i); 和 test(200); 最后都呼叫了 void process(int & i) 左值形參,
test(T && v) 接受test(i)的時候,是用左值去接, 接受test(200)的時候,使用右值去接,
其中有一點右值本身是一個左值型別(如何理解?右值本身是有地址有名稱的,所以他本身就可以取地址了,他是一個左值)
所以函式形參一定是個左值,他有名字,有空間了,變成了具名物件,200傳過去后變成了一個左值.
200 傳入 test后就變成了一個左值了,進入了test 函式后沒有保留好原始資訊,所以 process(v); 就都呼叫了void process(int & i) 左值形參,
這個我叫做 不完美轉發
但是我希望 在test 函式內任然能夠保留原始資訊,原始的是左值繼續保留左值,原始是右值就繼續保留右值, 如何實作呢? 完美轉發
參考折疊技術
形參 是 T && v ,在模板函式形參,兩個參考 在一起會引發參考折疊, 有一個左值參考 最后是=》左值, 兩個都是右值 最后是=>右值
即 test(i) + void test(T && v) => T & && i => 左值
即 test(200) + void test(T && v) => T && && 200 => 右值
所以將 函式形參寫成 &&
//模板實體化程序中出現這種情況就會發生參考折疊,如果任一尹永偉左值參考,那么結果就是左值參考,
//如果兩個都是右值參考,那么結果為右值參考
template<typename T>
void test2(T && v) {
std::cout <<"is int & " << std::is_same_v<T, int &> << std::endl;
std::cout << "is int " << std::is_same_v<T, int > << std::endl;
}
int main() {
int i = 100;
test2(i);
test2(200);
system("pause");
return 0;
}
template<typename T>
void test2(T && v) {
std::cout <<"is int & "<< std::is_same_v<T, int &> << std::endl;
std::cout << "is int " << std::is_same_v<T, int > << std::endl;
}
int main() {
int i = 100;
test2(i);
test2(200);
system("pause");
return 0;
}
test2(i) 呼叫模板會實體化出如下模板
void test2(int & && v) {
std::cout <<"is int & "<< std::is_same_v<T, int &> << std::endl;
std::cout << "is int " << std::is_same_v<T, int > << std::endl;
}
test2(200) 呼叫模板會實體化出如下模板
void test2(int && v) {
std::cout <<"is int & " << std::is_same_v<T, int &> << std::endl;
std::cout << "is int " << std::is_same_v<T, int > << std::endl;
}
上面兩個實體化出來的模板,形參根據參考折疊技術
void test2(int & && v) =》void test2(int & v)
void test2(int && v) =》void test2(int && v)
即 如果 test2(i) 那么模板中的 T 就是 int &
如果 test2(200 ) 那么模板中的 T 就是 int
所以 下面的代碼
template<typename T>
void test(T && v) { //這里的&& 表示萬能參考,既能接受左值也能接受右值
process(v);
}
我們這里這么改一下
template<typename T>
void test(T && v) { //這里的&& 表示萬能參考,既能接受左值也能接受右值
process(static_cast<T&&>(v));
// test(i) => process( static_cast<int & &&>(v)); => process( static_cast<int & >(v));
// test(200)=> process( static_cast<int &&>(v)); => process( static_cast<int && >(v));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/551560.html
標籤:其他
下一篇:返回列表