C++移動(dòng)語(yǔ)義介紹與使用講解
引入移動(dòng)語(yǔ)義
為了能夠理解移動(dòng)語(yǔ)義的目的,我們先從整成的一個(gè)類進(jìn)行示范,示例如下:
class TestClass
{
public:
TestClass(int s) :m_number(s) {
cout << "constructor!\n";
}
~TestClass() {
cout << "destructor!\n";
}
// 拷貝構(gòu)造
TestClass(const TestClass& that) :m_number(that.m_number) {
cout << "copy constructor!\n";
}
// 賦值操作符
TestClass& operator=(const TestClass& tc) {
cout << "operator= is called\n";
if (this == &tc)
return *this;
m_number = 0;
m_number = tc.m_number;
return *this;
}
int m_number;
};
TestClass tcFactory()
{
TestClass tc(10);
return tc;
}
int main()
{
{
TestClass tc = tcFactory();
}
return 0;
}上面代碼的輸出結(jié)果如下:
constructor!
copy constructor!
destructor!
destructor!
可以看到進(jìn)行了一次構(gòu)造和一次拷貝構(gòu)造,拷貝構(gòu)造就發(fā)生在tc 接收tcFactory()返回值時(shí)。這幾產(chǎn)生了不必要的資源消耗,如果這里可以重用或者轉(zhuǎn)移return產(chǎn)生的臨時(shí)值(右值)是不是可以減少資源的消耗呢?C++正是使用轉(zhuǎn)移的方式來(lái)處理的,這個(gè)轉(zhuǎn)移就是移動(dòng)構(gòu)造函數(shù),也可以說(shuō)是移動(dòng)語(yǔ)義,示例如下:
// 其他代碼不變,只增加移動(dòng)構(gòu)造與移動(dòng)賦值處理函數(shù)
// 移動(dòng)構(gòu)造
TestClass(TestClass&& rr):m_number(rr.m_number) {
// 如果這里是指針的變量的話則可以避免指針重復(fù)釋放的問(wèn)題
rr.m_number = 0;
cout << "move constructor!\n";
}
// 移動(dòng)賦值
TestClass& operator=(TestClass&& rr) {
cout << "move operator= is called\n";
if (this == &rr)
return *this;
// 此步驟相當(dāng)于對(duì)源指針的釋放
m_number = 0;
m_number = rr.m_number;
return *this;
}添加上述代碼后,輸出結(jié)果如下:
constructor!
move constructor!
destructor!
destructor!
此時(shí)第二次調(diào)用的就是移動(dòng)構(gòu)造,這樣可以直接使用右值,避免重新申請(qǐng)空間,調(diào)用兩次析構(gòu)是因?yàn)?,臨時(shí)對(duì)象是被延長(zhǎng)了聲明周期,但最終也是要釋放的。
std::move
前面看到移動(dòng)構(gòu)造接收的是右值引用,那么在需要對(duì)左值進(jìn)行移動(dòng)語(yǔ)義的時(shí)候(進(jìn)行移動(dòng)語(yǔ)義后,此左值以后將失效),那么就必須將左值轉(zhuǎn)換為右值。此時(shí)td::move就很好的完成了這件事情,示例如下:
int main()
{
vector<int> v{ 1,2,3,4 };
// 拷貝構(gòu)造
vector<int> v1 = v;
// 移動(dòng)構(gòu)造
vector<int> v2 = std::move(v);
cout << "v size():" << v.size() << "\n";
cout << "v2 size():" << v2.size() << "\n";
return 0;
}
上面輸出代碼為:
v size():0
v2 size():4
關(guān)于std::move注意的幾點(diǎn):
std::move本質(zhì)上只是將傳入的參數(shù)轉(zhuǎn)換為一個(gè)右值,使用static_cast進(jìn)行轉(zhuǎn)換
std::move在進(jìn)行類型推導(dǎo)時(shí)會(huì)保留形參的const屬性,此時(shí)會(huì)造成一種使用失效的場(chǎng)景如下:
class TestClass
{
public:
// 這么寫(xiě)在 VS中也會(huì)提示 C26478 不要對(duì)常量變量使用 std::move
TestClass(const string& str) :m_str(std::move(str)) {
}
string m_str;
};
int main()
{
string str = "sss";
TestClass tc(str);
cout << tc.m_str << "\n";
// 此處應(yīng)該輸出空,但實(shí)際并非如此 , 兩個(gè)輸出都是 sss
cout << str << "\n";
return 0;
}到此這篇關(guān)于C++移動(dòng)語(yǔ)義介紹與使用講解的文章就介紹到這了,更多相關(guān)C++移動(dòng)語(yǔ)義內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言求矩陣主對(duì)角線元素及副對(duì)角線元素之和
這篇文章主要介紹了C語(yǔ)言求矩陣主對(duì)角線元素及副對(duì)角線元素之和實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
C/C++中不同數(shù)據(jù)類型之間的轉(zhuǎn)換詳解
這篇文章主要介紹了C/C++中不同數(shù)據(jù)類型之間的轉(zhuǎn)換詳解,數(shù)據(jù)類型轉(zhuǎn)換是計(jì)算機(jī)編程中常見(jiàn)的操作,用于將一個(gè)數(shù)據(jù)類型轉(zhuǎn)換為另一個(gè)數(shù)據(jù)類型,本文將對(duì)不同數(shù)據(jù)類型之間的轉(zhuǎn)換作出說(shuō)明,需要的朋友可以參考下2023-10-10
C++二叉樹(shù)結(jié)構(gòu)的建立與基本操作
二叉樹(shù)是數(shù)據(jù)結(jié)構(gòu)中的樹(shù)的一種特殊情況,有關(guān)二叉樹(shù)的相關(guān)概念,這里不再贅述,如果不了解二叉樹(shù)相關(guān)概念,建議先學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)中的二叉樹(shù)的知識(shí)點(diǎn)2013-10-10
基礎(chǔ)C語(yǔ)言編程時(shí)易犯錯(cuò)誤有哪些
基礎(chǔ)C語(yǔ)言編程時(shí)易犯錯(cuò)誤有哪些?這篇文章主要介紹了C語(yǔ)言編程時(shí)常見(jiàn)的錯(cuò)誤,感興趣的小伙伴們可以參考一下2016-11-11
C++類成員構(gòu)造函數(shù)和析構(gòu)函數(shù)順序示例詳細(xì)講解
這篇文章主要介紹了C++類成員構(gòu)造和析構(gòu)順序示例,看了這個(gè)例子大家就可以明白c++構(gòu)造析構(gòu)的奧秘2013-11-11
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)哈希表詳解
哈希表是一種根據(jù)關(guān)鍵碼去尋找值的數(shù)據(jù)映射結(jié)構(gòu),該結(jié)構(gòu)通過(guò)把關(guān)鍵碼映射的位置去尋找存放值的地方,說(shuō)起來(lái)可能感覺(jué)有點(diǎn)復(fù)雜,我想我舉個(gè)例子你就會(huì)明白了,最典型的的例子就是字典2022-02-02

