當以一個函數內的臨時變量對象作為另一個函數的形參的時候,原函數內的臨時對象即 rvalue,就會成為此函數內的 lvalue。
這樣會重新導致效率低下,因為造成了大量復制操作。
<utility>頭文件提供了 std:move()函數。此函數返回作為 rvalue 傳遞給的任何實參。
觀察下面程序的輸出:
class CText { private: char *pText; public: void showIt()const { cout << pText << endl; } CText(const char* pStr = "No text") { cout << "CText constructor called" << endl; size_t len{ strlen(pStr) + 1 }; pText = new char[len]; strcpy_s(pText, len, pStr); } CText(const CText & txt) { cout << "CText copy constructor called" << endl; size_t len{ strlen(txt.pText) + 1 }; pText = new char[len]; strcpy_s(pText, len, txt.pText); } CText(CText && txt) { cout << "CText move constructor called" << endl; pText = txt.pText; txt.pText = nullptr; } ~CText() { cout << "CText destructor called" << endl; delete[]pText; } CText & operator=(const CText & txt) { cout << "CText assignment operator function called" << endl; if (this != &txt) { delete[]pText; size_t length{ strlen(txt.pText) + 1 }; pText = new char[length]; strcpy_s(pText, length, txt.pText); } return *this; } CText & operator=(CText && txt) { cout << "CText move assignment operator function called" << endl; delete[]pText; pText = txt.pText; txt.pText = nullptr; return *this; } CText operator+(const CText & txt)const { cout << "CText add operator function called" << endl; size_t length{ strlen(pText) + strlen(txt.pText) + 1 }; CText aText; aText.pText = new char[length]; strcpy_s(aText.pText, length, pText); strcat_s(aText.pText, length, txt.pText); return aText; } };
CText 實現了移動語義的復制構造和賦值運算符函數,並且CText的對象作為CMessage類的成員。
class CMessage { private: CText m_Text; public: void showIt()const { m_Text.showIt(); } CMessage operator+(const CMessage & aMess) const { cout << "CMessage add operator function called" << endl; CMessage message; message.m_Text = m_Text + aMess.m_Text; return message; } CMessage & operator=(const CMessage & aMess) { cout << "CMessage assignment operator function called" << endl; if (this != &aMess) { m_Text = aMess.m_Text; } return *this; } CMessage & operator=(CMessage && aMess) { cout << "CMessage move assignment operator function called" << endl; m_Text = aMess.m_Text; return *this; } CMessage(const char * str = "Default message")//:m_Text{ str }//m_Text { CText(str) } { cout << "CMessage constructor called----" << endl; m_Text = CText(str); } CMessage(const CMessage & amess) { cout << "cmessage copy constructor called" << endl; m_Text = amess.m_Text; } CMessage(const CMessage && amess) { cout << "cmessage move constructor called" << endl; m_Text = amess.m_Text; } }; int main() { CMessage motto1{"The devi1 takes care of his own.\n"}; cout << "----------------------------------------" << endl; CMessage motto2{"if yuo sup with the devil use a long spoon.\n"}; cout << "----------------------------------------" << endl; CMessage motto3{motto1+motto2}; cout << "----------------------------------------" << endl; motto3.showIt(); }
注意:CMessage 的構造函數,用初始化列表和在構造函數中初始化的差別。
當用初始化列表的輸出如下: