C++移動語義介紹與使用講解
引入移動語義
為了能夠理解移動語義的目的,我們先從整成的一個類進行示范,示例如下:
class TestClass
{
public:
TestClass(int s) :m_number(s) {
cout << "constructor!\n";
}
~TestClass() {
cout << "destructor!\n";
}
// 拷貝構造
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;
}上面代碼的輸出結果如下:
constructor!
copy constructor!
destructor!
destructor!
可以看到進行了一次構造和一次拷貝構造,拷貝構造就發(fā)生在tc 接收tcFactory()返回值時。這幾產生了不必要的資源消耗,如果這里可以重用或者轉移return產生的臨時值(右值)是不是可以減少資源的消耗呢?C++正是使用轉移的方式來處理的,這個轉移就是移動構造函數(shù),也可以說是移動語義,示例如下:
// 其他代碼不變,只增加移動構造與移動賦值處理函數(shù)
// 移動構造
TestClass(TestClass&& rr):m_number(rr.m_number) {
// 如果這里是指針的變量的話則可以避免指針重復釋放的問題
rr.m_number = 0;
cout << "move constructor!\n";
}
// 移動賦值
TestClass& operator=(TestClass&& rr) {
cout << "move operator= is called\n";
if (this == &rr)
return *this;
// 此步驟相當于對源指針的釋放
m_number = 0;
m_number = rr.m_number;
return *this;
}添加上述代碼后,輸出結果如下:
constructor!
move constructor!
destructor!
destructor!
此時第二次調用的就是移動構造,這樣可以直接使用右值,避免重新申請空間,調用兩次析構是因為,臨時對象是被延長了聲明周期,但最終也是要釋放的。
std::move
前面看到移動構造接收的是右值引用,那么在需要對左值進行移動語義的時候(進行移動語義后,此左值以后將失效),那么就必須將左值轉換為右值。此時td::move就很好的完成了這件事情,示例如下:
int main()
{
vector<int> v{ 1,2,3,4 };
// 拷貝構造
vector<int> v1 = v;
// 移動構造
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
關于std::move注意的幾點:
std::move本質上只是將傳入的參數(shù)轉換為一個右值,使用static_cast進行轉換
std::move在進行類型推導時會保留形參的const屬性,此時會造成一種使用失效的場景如下:
class TestClass
{
public:
// 這么寫在 VS中也會提示 C26478 不要對常量變量使用 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";
// 此處應該輸出空,但實際并非如此 , 兩個輸出都是 sss
cout << str << "\n";
return 0;
}到此這篇關于C++移動語義介紹與使用講解的文章就介紹到這了,更多相關C++移動語義內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++類成員構造函數(shù)和析構函數(shù)順序示例詳細講解
這篇文章主要介紹了C++類成員構造和析構順序示例,看了這個例子大家就可以明白c++構造析構的奧秘2013-11-11

