c++11之右值引用和std::move


  • 這兩個特性是c++11里比較有性能提升意義的。個人認為這兩個特性也體現了c++對性能提升的極限追求。
  • 通過改寫經典c++面試題mystring來體會
  • move不能減少臨時變量的產生,但是可以減少內存的維護量
  • 代碼
      1. //右值引用
      2. /*
      3. 左值對象:持久存在的對象,具有名字,可以對其去地址
      4. 右值對象:臨時對象,表達式結束后它就沒了,不能對它取地址,它也沒有名字~
      5. 右值引用類型:引用右值的類型,用&&來表示
      6. */
      7. /************************************************************************/
      8. /*使用右值引用改進MyString類,添加移動構造函數 */
      9. /************************************************************************/
      10. #include<iostream>
      11. #include<vector>
      12. usingnamespace std;
      13. classMyString
      14. {
      15. public:
      16. //普通構造函數
      17. MyString()
      18. {
      19. cout <<"\n default construct\n";
      20. mLength =0;
      21. mData = NULL;
      22. }
      23. //帶參數的普通構造函數
      24. MyString(constchar* str)
      25. {
      26. cout <<"\n arg construct\n";
      27. mLength = strlen(str);
      28. mData =newchar[mLength+1];
      29. memcpy(mData, str, mLength);
      30. mData[mLength]='\0';
      31. }
      32. //拷貝構造函數
      33. MyString(constMyString& str)
      34. {
      35. cout <<"\n copy construct\n";
      36. //深拷貝
      37. mLength = str.mLength;
      38. mData =newchar[mLength +1];
      39. memcpy(mData,str.mData,mLength);
      40. mData[mLength]='\0';
      41. }
      42. //移動構造函數
      43. MyString(MyString&& str)
      44. {
      45. cout <<"\n move construct\n";
      46. mLength = str.mLength;
      47. mData = str.mData;
      48. //
      49. str.mLength =0;
      50. str.mData = NULL;//這個是必須的,否則臨時對象和此對象指向同一個資源,臨時對象析構時會釋放資源導致錯誤
      51. }
      52. //賦值函數
      53. MyString&operator=(constMyString& str)
      54. {
      55. cout <<"\n operator = \n";
      56. if(this!=&str)
      57. {
      58. if(mData)
      59. {
      60. delete[] mData;
      61. }
      62. mLength = str.mLength;
      63. mData =newchar[mLength +1];
      64. memcpy(mData, str.mData, mLength);
      65. mData[mLength]='\0';
      66. }
      67. return*this;
      68. }
      69. //右值賦值函數
      70. MyString&operator=(MyString&& str)
      71. {
      72. cout <<"\n right ref operator = \n";
      73. if(this!=&str)
      74. {
      75. if(mData)
      76. {
      77. delete[] mData;
      78. }
      79. mLength = str.mLength;
      80. mData = str.mData;
      81. str.mLength =0;
      82. str.mData = NULL;
      83. }
      84. return*this;
      85. }
      86. //析構函數
      87. ~MyString()
      88. {
      89. cout <<"\n destruct \n";
      90. if(mData)
      91. {
      92. delete[] mData;
      93. mData = NULL;
      94. }
      95. }
      96. public:
      97. size_t mLength;
      98. char* mData;
      99. };
      100. MyStringGetString()
      101. {
      102. MyString str("test str");
      103. return str;
      104. }
      105. int main()
      106. {
      107. int i =0;
      108. //i是左值,0是右值
      109. MyString a;
      110. MyString b("b");
      111. //這兩個寫法,對於編譯器來說是一樣的
      112. MyString c(b);
      113. MyString d = c;//這個只調用拷貝構造函數,不會調用賦值函數;分兩行寫就會調用賦值,為什么會這樣。。。
      114. MyString e =GetString();
      115. MyString f(GetString());//調用移動構造函數
      116. MyString h;
      117. h =MyString();//調用右值賦值函數
      118. MyString g;
      119. g = e;//調用賦值函數
      120. MyString m;
      121. m =GetString();
      122. vector<MyString> v;
      123. MyString str("123");
      124. v.push_back(str);//會創建臨時變量,調用拷貝構造函數
      125. v.push_back(std::move(str));//調用移動構造函數,std::move將左值引用轉化為右值引用,
      126. //push_back在接受右值引用后調用類的移動構造函數將資源移動到
      127. //容器中,而右值引用對應的對象具體處理要參考具體移動構造函數的實現。我這里是將資源設null了。
      128. //移動語義的使用場合
      129. /************************************************************************/
      130. /* 目的,通過右值和資源移動來實現臨時對象資源的所有權轉移,減少內存操作(申請拷貝釋放),對含有堆資源的對象才比較有意義,而且必須實現相應的移動構造函數 */
      131. /************************************************************************/
      132. }
       






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM