move : 移動(dòng)語義,得到右值類型
forward:類型轉(zhuǎn)發(fā),能夠識(shí)別左值和右值類型
只有兩種形式的引用,左值引用和右值引用,萬能引用不是一種引用類型,它存在于模板的引用折疊情況,但是能夠接受左值和右值
區(qū)分左值和右值得一個(gè)簡單方式就是能不能取地址
一個(gè)右值一旦有名字那么就變成了左值
#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;
}
上面的運(yùn)行結(jié)果 我們發(fā)現(xiàn) test(i); 和 test(200); 最后都調(diào)用了 void process(int & i) 左值形參,
test(T && v) 接受test(i)的時(shí)候,是用左值去接, 接受test(200)的時(shí)候,使用右值去接,
其中有一點(diǎn)右值本身是一個(gè)左值類型(如何理解?右值本身是有地址有名稱的,所以他本身就可以取地址了,他是一個(gè)左值)
所以函數(shù)形參一定是個(gè)左值,他有名字,有空間了,變成了具名對象,200傳過去后變成了一個(gè)左值.
200 傳入 test后就變成了一個(gè)左值了,進(jìn)入了test 函數(shù)后沒有保留好原始信息,所以 process(v); 就都調(diào)用了void process(int & i) 左值形參,
這個(gè)我叫做 不完美轉(zhuǎn)發(fā)
但是我希望 在test 函數(shù)內(nèi)任然能夠保留原始信息,原始的是左值繼續(xù)保留左值,原始是右值就繼續(xù)保留右值, 如何實(shí)現(xiàn)呢? 完美轉(zhuǎn)發(fā)
引用折疊技術(shù)
形參 是 T && v ,在模板函數(shù)形參,兩個(gè)引用 在一起會(huì)引發(fā)引用折疊, 有一個(gè)左值引用 最后是=》左值, 兩個(gè)都是右值 最后是=>右值
即 test(i) + void test(T && v) => T & && i => 左值
即 test(200) + void test(T && v) => T && && 200 => 右值
所以將 函數(shù)形參寫成 &&文章來源:http://www.zghlxwxcb.cn/news/detail-433173.html
//模板實(shí)例化過程中出現(xiàn)這種情況就會(huì)發(fā)生引用折疊,如果任一尹永偉左值引用,那么結(jié)果就是左值引用,
//如果兩個(gè)都是右值引用,那么結(jié)果為右值引用
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;
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-433173.html
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) 調(diào)用模板會(huì)實(shí)例化出如下模板
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) 調(diào)用模板會(huì)實(shí)例化出如下模板
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;
}
上面兩個(gè)實(shí)例化出來的模板,形參根據(jù)引用折疊技術(shù)
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));
}
到了這里,關(guān)于<五>move移動(dòng)語義和forward類型轉(zhuǎn)發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!