移動建構函式和移動賦值函數

來源:互聯網
上載者:User

標籤:c++

在一個類的內部同時實現常規拷貝建構函式和移動拷貝建構函式,常規賦值函數和移動賦值函數。
調用時若參數為一個左值,則調用常規函數;若參數為一個右值,則調用移動函數。
也可調用"std::move"強行調用移動函數。

#include <iostream>#include <utility>using std::cout;using std::endl;class Useless{private:    int n;          // number of elements    char * pc;      // pointer to data    static int ct;  // number of objectspublic:    Useless();    explicit Useless(int k);    Useless(int k, char ch);    Useless(const Useless & f); // regular copy constructor    Useless(Useless && f);      // move constructor    ~Useless();    Useless operator+(const Useless & f)const;    Useless & operator=(const Useless & f); // copy assignment    Useless & operator=(Useless && f);      // move assignment     void ShowObject() const;};// implementationint Useless::ct = 0;Useless::Useless(){    cout << "enter " << __func__ << "()\n";    ++ct;    n = 0;    pc = nullptr;    ShowObject();    cout << "leave " << __func__ << "()\n"; }Useless::Useless(int k) : n(k){    cout << "enter " << __func__ << "(k)\n";    ++ct;     pc = new char[n];    ShowObject();    cout << "leave " << __func__ << "(k)\n";}Useless::Useless(int k, char ch) : n(k){    cout << "enter " << __func__ << "(k, ch)\n";    ++ct;    pc = new char[n];    for (int i = 0; i < n; i++)        pc[i] = ch;    ShowObject();    cout << "leave " << __func__ << "(k, ch)\n";}Useless::Useless(const Useless & f): n(f.n) {    cout << "enter " << __func__ << "(const &)\n";    ++ct;    pc = new char[n];    for (int i = 0; i < n; i++)        pc[i] = f.pc[i];    ShowObject();    cout << "leave " << __func__ << "(const &)\n";}Useless::Useless(Useless && f): n(f.n) {    cout << "enter " << __func__ << "(&&)\n";    ++ct;    pc = f.pc;       // steal address    f.pc = nullptr;  // give old object nothing in return    f.n = 0;    ShowObject();    f.ShowObject();    cout << "leave " << __func__ << "(&&)\n";}Useless::~Useless(){    cout << "enter " << __func__ << "()\n";    ShowObject();    --ct;    delete [] pc;    cout << "leave " << __func__ << "()\n";}Useless & Useless::operator=(const Useless & f)  // copy assignment{    cout << "enter " << __func__ << "(const &)\n";    ShowObject();    f.ShowObject();    if (this == &f)        return *this;    delete [] pc;    n = f.n;    pc = new char[n];    for (int i = 0; i < n; i++)        pc[i] = f.pc[i];    ShowObject();    f.ShowObject();    cout << "leave " << __func__ << "(const &)\n";    return *this;}Useless & Useless::operator=(Useless && f)       // move assignment{    cout << "enter " << __func__ << "(&&)\n";    ShowObject();    f.ShowObject();    if (this == &f)        return *this;    delete [] pc;    n = f.n;    pc = f.pc;    f.n = 0;    f.pc = nullptr;    ShowObject();    f.ShowObject();    cout << "leave " << __func__ << "(&&)\n";    return *this;}Useless Useless::operator+(const Useless & f)const{    cout << "enter " << __func__ << "(const &)\n";    ShowObject();    f.ShowObject();    Useless temp = Useless(n + f.n);    for (int i = 0; i < n; i++)        temp.pc[i] = pc[i];    for (int i = n; i < temp.n; i++)        temp.pc[i] = f.pc[i - n];    cout << "\t temp: ";    temp.ShowObject();    cout << "leave " << __func__ << "(const &)\n";    return temp;}void Useless::ShowObject() const{     cout << "\t this=" << this << ", ct=" << ct;     cout << ", pc=(" << n << ", " << (void*)pc << ", ";     if (n == 0)        cout << "(object empty)";    else        for (int i = 0; i < n; i++)            cout << pc[i];    cout << endl;}// applicationint main(){    Useless one(10, ‘x‘);    Useless two = one + one;   // calls move constructor    cout << "object one:\n";    one.ShowObject();    cout << "object two:\n";    two.ShowObject();    Useless three, four;    cout << "three = one\n";    three = one;              // automatic copy assignment    cout << "now object three:\n";    three.ShowObject();    cout << "and object one:\n";    one.ShowObject();    cout << "four = one + two\n";    four = one + two;         // automatic move assignment    cout << "now object four:\n";    four.ShowObject();    cout << "four = move(one)\n";    four = std::move(one);    // forced move assignment    cout << "now object four:\n";    four.ShowObject();    cout << "and object one:\n";    one.ShowObject();     std::cin.get();}

測試結果如下。紅色部分不是測試結果的一部分,是對測試結果的分析。

enter Useless(k, ch)
         this=0x7fffb5ade0f0, ct=1, pc=(10, 0x23f7010, xxxxxxxxxx
leave Useless(k, ch)
enter operator+(const &)
         this=0x7fffb5ade0f0, ct=1, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade0f0, ct=1, pc=(10, 0x23f7010, xxxxxxxxxx
enter Useless(k)
         this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030,
leave Useless(k)
         temp:   this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
leave operator+(const &)
object one:
         this=0x7fffb5ade0f0, ct=2, pc=(10, 0x23f7010, xxxxxxxxxx
object two:
         this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
         //"Useless two = one +one;"
         //首先調用"operator+(const &)",在這個函數內調用"Useless(k)"產生temp對象。
         //返回時調用拷貝建構函式產生一個臨時匿名對象。
         //析構temp對象。
         //然後再調用移動拷貝建構函式,產生對象two。
         //析構臨時匿名對象。
         //當前gcc版本是g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4,對編譯過程做了改進,直接把temp對象和two對象當成一個對象,省去了後面四步。
enter Useless()
         this=0x7fffb5ade110, ct=3, pc=(0, 0, (object empty)
leave Useless()
enter Useless()
         this=0x7fffb5ade120, ct=4, pc=(0, 0, (object empty)
leave Useless()
three = one
enter operator=(const &)
         this=0x7fffb5ade110, ct=4, pc=(0, 0, (object empty)
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade110, ct=4, pc=(10, 0x23f7050, xxxxxxxxxx
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
leave operator=(const &)
now object three:
         this=0x7fffb5ade110, ct=4, pc=(10, 0x23f7050, xxxxxxxxxx
and object one:
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
four = one + two
enter operator+(const &)
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade100, ct=4, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
enter Useless(k)
         this=0x7fffb5ade130, ct=5, pc=(30, 0x23f7070,
leave Useless(k)
         temp:   this=0x7fffb5ade130, ct=5, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
leave operator+(const &)
//"four = one + two"首先調用"operator+(const &)"函數。在這個函數內產生temp對象。
//在返回"operator+(const &)"函數後,並沒有產生一個臨時匿名對象,也沒有析構temp對象,而是直接以temp做參數調用移動拷貝函數"operator=(&&)"。
enter operator=(&&)
         this=0x7fffb5ade120, ct=5, pc=(0, 0, (object empty)
         this=0x7fffb5ade130, ct=5, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         this=0x7fffb5ade120, ct=5, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         this=0x7fffb5ade130, ct=5, pc=(0, 0, (object empty)
leave operator=(&&)
//在返回"operator=(&&)"函數後才析構temp對象。
enter ~Useless()
         this=0x7fffb5ade130, ct=5, pc=(0, 0, (object empty)
leave ~Useless()
now object four:
         this=0x7fffb5ade120, ct=4, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
four = move(one)
//"four = std::move(one);"強行調用移動賦值函數"operator=(&&)"。
//調用之後,four對象接管了one對象的內部資源(pc和n),one對象沒有被析構,但內部資源被“掏空”了!
enter operator=(&&)
         this=0x7fffb5ade120, ct=4, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade120, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade0f0, ct=4, pc=(0, 0, (object empty)
leave operator=(&&)
now object four:
         this=0x7fffb5ade120, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
and object one:
         this=0x7fffb5ade0f0, ct=4, pc=(0, 0, (object empty)

//退出"main()"時,析構棧空間的對象。析構順序與構造順序相反。
enter ~Useless()
         this=0x7fffb5ade120, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
leave ~Useless()
enter ~Useless()
         this=0x7fffb5ade110, ct=3, pc=(10, 0x23f7050, xxxxxxxxxx
leave ~Useless()
enter ~Useless()
         this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
leave ~Useless()
enter ~Useless()
         this=0x7fffb5ade0f0, ct=1, pc=(0, 0, (object empty)
leave ~Useless()


本文出自 “用C++寫詩” 部落格,謝絕轉載!

移動建構函式和移動賦值函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.