日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++移動語義介紹與使用講解_C 語言

作者:憤怒的小黃鴨 ? 更新時間: 2022-10-27 編程語言

引入移動語義

為了能夠理解移動語義的目的,我們先從整成的一個類進行示范,示例如下:

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!

可以看到進行了一次構造和一次拷貝構造,拷貝構造就發生在tc 接收tcFactory()返回值時。這幾產生了不必要的資源消耗,如果這里可以重用或者轉移return產生的臨時值(右值)是不是可以減少資源的消耗呢?C++正是使用轉移的方式來處理的,這個轉移就是移動構造函數,也可以說是移動語義,示例如下:

// 其他代碼不變,只增加移動構造與移動賦值處理函數
// 移動構造
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本質上只是將傳入的參數轉換為一個右值,使用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;
}

原文鏈接:https://blog.csdn.net/weixin_41111116/article/details/126452636

欄目分類
最近更新