C++11中std::move、std::forward、左右值引用、移動(dòng)構(gòu)造函數(shù)的測(cè)試問題
關(guān)于C++11新特性之std::move、std::forward、左右值引用網(wǎng)上資料已經(jīng)很多了,我主要針對(duì)測(cè)試性能做一個(gè)測(cè)試,梳理一下這些邏輯,首先,左值比較熟悉,右值就是臨時(shí)變量,意味著使用一次就不會(huì)再被使用了。針對(duì)這兩種值引入了左值引用和右值引用,以及引用折疊的概念。
1.右值引用的舉例測(cè)試
#include <iostream> using namespace std; //創(chuàng)建一個(gè)測(cè)試類 class A { public: A() : m_a(55) { } int m_a; }; void funcA(A&& param) // 右值引用參數(shù),只接受右值 { cout << param.m_a << endl; // param與a的地址一致,僅僅只是取了一個(gè)新名字 } int main() { A a; funcA(move(a)); //必須將其轉(zhuǎn)換為右值 cout << a.m_a << endl; //正常打印,所以std::move并沒有移動(dòng)的能力 return 0; }
2.左值和右值引用的舉例測(cè)試,以及引出萬能引用
構(gòu)造一組重載函數(shù),分別接受右值,和左值的參數(shù),還有const A&的參數(shù)重載函數(shù)。
void funcA(const A& param)//既可以接受右值引用,也可以接受左值引用,但是有一個(gè)隱式轉(zhuǎn)換const A& void funcA(A& param)// 接受左值引用 void funcA(A&& param) // 接受右值引用
const A& param既可以接受右值引用,也可以接受左值引用,但是存在一個(gè)隱式轉(zhuǎn)換,const使用受限制。
#include <iostream> using namespace std; //創(chuàng)建一個(gè)測(cè)試類 class A { public: A() : m_a(55) // 構(gòu)造函數(shù) { cout << "Constructor" << endl; } A(const A & other) : m_a(55) // copy構(gòu)造函數(shù) { cout << "Copy Constructor" << endl; if (this == &other) { return; } this->m_a = other.m_a; } A& operator=(const A& other) // 賦值構(gòu)造函數(shù) { cout << "= Constructor" << endl; if (this == &other) { return *this; } this->m_a = other.m_a; return *this; } int m_a; }; void test(A&& pa) //測(cè)試是否為右值 { cout << "只接受右值" << endl; } void funcA(const A& param) // 既可以接受右值引用,也可以接受左值引用,但是有一個(gè)隱式轉(zhuǎn)換const A& { //test(param); //編譯不過,param可以接受右值,但是param被轉(zhuǎn)換為const左值 //test(std::forward<A>(param)); //編譯不過,param可以接受右值,但是param被轉(zhuǎn)換為const左值 cout << param.m_a << endl; } void funcA(A& param) // 接受左值引用 { //test(param); //編譯不過,param可以接受右值,但是param被轉(zhuǎn)換為左值 test(std::forward<A>(param)); //編譯通過,通過forward轉(zhuǎn)發(fā) cout << param.m_a << endl; } void funcA(A&& param) // 接受右值引用 { //test(param); //編譯不過,param被轉(zhuǎn)換為左值 test(std::forward<A>(param)); //編譯通過,通過forward轉(zhuǎn)發(fā) cout << param.m_a << endl; } int main() { A a; const A& b = a; funcA(a); funcA(move(a)); funcA(b); cout << a.m_a << endl; //正常打印,所以std::move并沒有移動(dòng)的能力 return 0; }
對(duì)此C++11引入了萬能引用的概念,使得不需要那么多的重載函數(shù),既可以接受右值引用,也可以接受左值引用。但是函數(shù)內(nèi)部,再需要調(diào)用一個(gè)左值或者右值的函數(shù)時(shí),我們就得需要forward模版類。
#include <iostream> using namespace std; //創(chuàng)建一個(gè)測(cè)試類 class A { public: A() : m_a(new int(55)) // 構(gòu)造函數(shù) { cout << "Constructor" << endl; } A(const A & other) : m_a(new int(55)) // copy構(gòu)造函數(shù) { cout << "Copy Constructor" << endl; if (this == &other) return; this->m_a = other.m_a; } A& operator=(const A& other) // 賦值構(gòu)造函數(shù) { cout << "= Constructor" << endl; if (this == &other) return *this; this->m_a = other.m_a; return *this; } int* m_a; }; void test(A&& pa) //測(cè)試是否為右值 { cout << "只接受右值" << endl; } void test(A& pa) //測(cè)試是否為左值 { cout << "只接受左值" << endl; } template<class T> void funcA(T&& param) { test(std::forward<T>(param)); //編譯通過,通過forward完美轉(zhuǎn)發(fā) cout << *param.m_a << endl; } int main() { A a; funcA(a); funcA(move(a)); cout << *a.m_a << endl; //正常打印,所以std::move并沒有移動(dòng)的能力 return 0; }
3.移動(dòng)構(gòu)造函數(shù)的引出
以上的所有特性,所能體現(xiàn)出來的是我們對(duì)于臨時(shí)變量的使用,盡可能的使用中間生成的臨時(shí)變量,提高性能,所謂的榨取最后的性能。移動(dòng)構(gòu)造函數(shù)注意的兩點(diǎn)
1.調(diào)用移動(dòng)構(gòu)造函數(shù)時(shí)參數(shù)(被移動(dòng)者)必須是右值。
2.調(diào)用移動(dòng)構(gòu)造函數(shù)后被移動(dòng)者就不能再被使用。
#include <iostream> using namespace std; //創(chuàng)建一個(gè)測(cè)試類 class A { public: A() : m_a(new int(55)) // 構(gòu)造函數(shù) { cout << "Constructor" << endl; } A(const A & other) : m_a(new int(55)) // copy構(gòu)造函數(shù) { cout << "Copy Constructor" << endl; if (this == &other) { return; } this->m_a = other.m_a; } A& operator=(const A& other) // 賦值構(gòu)造函數(shù) { cout << "= Constructor" << endl; if (this == &other) { return *this; } this->m_a = other.m_a; return *this; } A(A&& other) : m_a(other.m_a) // 移動(dòng)構(gòu)造函數(shù),參數(shù)是一個(gè)右值, { cout << "Move Constructor" << endl; if (this == &other) { return; } other.m_a = nullptr; //移動(dòng)后將被移動(dòng)的對(duì)象數(shù)據(jù)清空 } int* m_a; }; void test(A&& pa) //測(cè)試是否為右值 { cout << "只接受右值" << endl; } void test(A& pa) //測(cè)試是否為左值 { cout << "只接受左值" << endl; } template<class T> void funcA(T&& param) { test(std::forward<T>(param)); //編譯通過,通過forward完美轉(zhuǎn)發(fā) cout << *param.m_a << endl; } int main() { A a; funcA(a); funcA(move(a)); A b(move(a)); //調(diào)用移動(dòng)構(gòu)造函數(shù),新的對(duì)象是b對(duì)象 cout << *a.m_a << endl; //數(shù)據(jù)已被移動(dòng),程序崩潰 return 0; }
移動(dòng)構(gòu)造函數(shù)一定程度上較少了臨時(shí)內(nèi)存的申請(qǐng),減少不必要的拷貝,節(jié)省了空間和時(shí)間。以上特性在使用中還有很多需要注意的地方,如果我遇到了會(huì)及時(shí)的添加到這里,分享給大家,一起加油。
到此這篇關(guān)于C++11中std::move、std::forward、左右值引用、移動(dòng)構(gòu)造函數(shù)的測(cè)試問題的文章就介紹到這了,更多相關(guān)C++11中std::move、std 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言開發(fā)實(shí)現(xiàn)井字棋及電腦落子優(yōu)化示例詳解
以前上課經(jīng)常和同桌玩起井字棋,那么我們就當(dāng)我們回憶童年,現(xiàn)在也用C語(yǔ)言來實(shí)現(xiàn)井字棋,本次代碼相對(duì)于初階的井字棋,在電腦下棋代碼部分做了優(yōu)化,使得電腦更加具有威脅2021-11-11