C++11中std::move、std::forward、左右值引用、移動構(gòu)造函數(shù)的測試問題
關(guān)于C++11新特性之std::move、std::forward、左右值引用網(wǎng)上資料已經(jīng)很多了,我主要針對測試性能做一個測試,梳理一下這些邏輯,首先,左值比較熟悉,右值就是臨時變量,意味著使用一次就不會再被使用了。針對這兩種值引入了左值引用和右值引用,以及引用折疊的概念。
1.右值引用的舉例測試
#include <iostream>
using namespace std;
//創(chuàng)建一個測試類
class A
{
public:
A() : m_a(55)
{
}
int m_a;
};
void funcA(A&& param) // 右值引用參數(shù),只接受右值
{
cout << param.m_a << endl; // param與a的地址一致,僅僅只是取了一個新名字
}
int main()
{
A a;
funcA(move(a)); //必須將其轉(zhuǎn)換為右值
cout << a.m_a << endl; //正常打印,所以std::move并沒有移動的能力
return 0;
}
2.左值和右值引用的舉例測試,以及引出萬能引用
構(gòu)造一組重載函數(shù),分別接受右值,和左值的參數(shù),還有const A&的參數(shù)重載函數(shù)。
void funcA(const A& param)//既可以接受右值引用,也可以接受左值引用,但是有一個隱式轉(zhuǎn)換const A& void funcA(A& param)// 接受左值引用 void funcA(A&& param) // 接受右值引用
const A& param既可以接受右值引用,也可以接受左值引用,但是存在一個隱式轉(zhuǎn)換,const使用受限制。
#include <iostream>
using namespace std;
//創(chuàng)建一個測試類
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) //測試是否為右值
{
cout << "只接受右值" << endl;
}
void funcA(const A& param) // 既可以接受右值引用,也可以接受左值引用,但是有一個隱式轉(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并沒有移動的能力
return 0;
}
對此C++11引入了萬能引用的概念,使得不需要那么多的重載函數(shù),既可以接受右值引用,也可以接受左值引用。但是函數(shù)內(nèi)部,再需要調(diào)用一個左值或者右值的函數(shù)時,我們就得需要forward模版類。
#include <iostream>
using namespace std;
//創(chuàng)建一個測試類
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) //測試是否為右值
{
cout << "只接受右值" << endl;
}
void test(A& pa) //測試是否為左值
{
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并沒有移動的能力
return 0;
}
3.移動構(gòu)造函數(shù)的引出
以上的所有特性,所能體現(xiàn)出來的是我們對于臨時變量的使用,盡可能的使用中間生成的臨時變量,提高性能,所謂的榨取最后的性能。移動構(gòu)造函數(shù)注意的兩點
1.調(diào)用移動構(gòu)造函數(shù)時參數(shù)(被移動者)必須是右值。
2.調(diào)用移動構(gòu)造函數(shù)后被移動者就不能再被使用。
#include <iostream>
using namespace std;
//創(chuàng)建一個測試類
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) // 移動構(gòu)造函數(shù),參數(shù)是一個右值,
{
cout << "Move Constructor" << endl;
if (this == &other)
{
return;
}
other.m_a = nullptr; //移動后將被移動的對象數(shù)據(jù)清空
}
int* m_a;
};
void test(A&& pa) //測試是否為右值
{
cout << "只接受右值" << endl;
}
void test(A& pa) //測試是否為左值
{
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)用移動構(gòu)造函數(shù),新的對象是b對象
cout << *a.m_a << endl; //數(shù)據(jù)已被移動,程序崩潰
return 0;
}
移動構(gòu)造函數(shù)一定程度上較少了臨時內(nèi)存的申請,減少不必要的拷貝,節(jié)省了空間和時間。以上特性在使用中還有很多需要注意的地方,如果我遇到了會及時的添加到這里,分享給大家,一起加油。
到此這篇關(guān)于C++11中std::move、std::forward、左右值引用、移動構(gòu)造函數(shù)的測試問題的文章就介紹到這了,更多相關(guān)C++11中std::move、std 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ Cartographer源碼中關(guān)于Sensor的數(shù)據(jù)走向深扒
這篇文章主要介紹了C++ Cartographer源碼中關(guān)于Sensor的數(shù)據(jù)走向,整個Cartographer源碼閱讀是很枯燥的, 但絕對是可以學(xué)到東西的,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
C語言 數(shù)據(jù)結(jié)構(gòu)中棧的實現(xiàn)代碼
這篇文章主要介紹了C語言 數(shù)據(jù)結(jié)構(gòu)中棧的實現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10
vscode使用cmake時將命令行參數(shù)傳遞給調(diào)試目標的方法
這篇文章主要介紹了vscode使用cmake時將命令行參數(shù)傳遞給調(diào)試目標,下面介紹了一個示例,將參數(shù)first_arg, second-arg和third arg傳遞給程序(此處需要注意,third arg中間雖然存在空格,但是仍然被視作一個參數(shù)),需要的朋友參考下吧2024-03-03

