1. 程式人生 > >Visual Studio2010新特性--C++王者歸來(3-泛型程式設計-轉移建構函式

Visual Studio2010新特性--C++王者歸來(3-泛型程式設計-轉移建構函式

               

泛型程式設計(generic programming)關注於產生通用的軟體元件,讓這些元件在不同的應用場合都能很容易地重用。在c++中,類模板和函式模板是進行泛型程式設計極為有效的機制。

什麼是臨時物件?定義:當且僅當離開一段上下文(context)時在物件上執行的僅有的操作是解構函式時,一個物件被看成是臨時的。這裡上下文可能是一個表示式,也可能是一個語句範圍,例如函式體。

建立、複製和銷燬臨時物件是vc++編譯器乾的最多的事情,但臨時物件會降低效能.轉移建構函式就是解決C++存在的不必要的複製問題的方法。

物件生成器物件生成器是一種函式模板,依據其引數產生新的物件。可以把它想象成泛型化的建構函式。有些情況下,欲生成的物件的精確型別很難甚至根本無法表示出來,這時物件生成器可就管用了。物件生成器的優點還在於它的返回值可以直接作為函式引數,而不像建構函式那樣只有在定義變數時才會呼叫。移動構函式就是為了解決C++存在的不必要的複製問題的方法。

VC++2010在c++語言裡面增加了一個特殊的新特性,轉移建構函式,解決C++存在的不必要的複製問題的方法。

程式碼由vc++2010除錯通過!備有詳細的註釋![cpp] view plain copy print?
  1. #include "stdafx.h"
  2. #include <vector>
  3. #include <iostream>
  4. usingnamespace std;  
  5. bool g_bTraceOutput = true;  
  6. class CSomeObject  
  7. {  
  8. public:  
  9.     CSomeObject()  
  10.         : m_iBufferSize(0)  
  11.         , m_pBuffer(NULL)  
  12.         , m_iInstanceID(ms_iInstanceCounter++)  
  13.     {  
  14.     }  
  15.     // 普通建構函式
  16.     CSomeObject(unsigned int iBufferSize)  
  17.         : m_iBufferSize(iBufferSize)  
  18.         , m_pBuffer(NULL)  
  19.         , m_iInstanceID(ms_iInstanceCounter++)  
  20.     {  
  21.         if (g_bTraceOutput)  
  22.             cout << "In NORMAL constructor for ID "
     << m_iInstanceID << " (size=" << m_iBufferSize << ")" << endl;  
  23.         if (m_iBufferSize > 0)  
  24.         {  
  25.             m_pBuffer = newchar[m_iBufferSize];  
  26.             memset(m_pBuffer, 0, m_iBufferSize);  
  27.         }  
  28.     }  
  29.     // 拷貝建構函式
  30.     CSomeObject(const CSomeObject& objSource)  
  31.         : m_iInstanceID(ms_iInstanceCounter++)  
  32.     {  
  33.         if (g_bTraceOutput)  
  34.             cout << "In COPY constructor from ID " << objSource.m_iInstanceID  << " to ID " << m_iInstanceID << " (size=" << objSource.m_iBufferSize << ")" << endl;  
  35.         m_iBufferSize = objSource.m_iBufferSize;  
  36.         if (m_iBufferSize > 0)  
  37.         {  
  38.             m_pBuffer = newchar[m_iBufferSize];  
  39.             memset(m_pBuffer, 0, m_iBufferSize);  
  40.         }  
  41.     }  
  42.     ~CSomeObject()  
  43.     {  
  44.         if (g_bTraceOutput)  
  45.             cout << "In destructor for ID " << m_iInstanceID << " (size=" << m_iBufferSize << ")" << endl;  
  46.         if (m_pBuffer)  
  47.             delete [] m_pBuffer;  
  48.         m_pBuffer = NULL;  
  49.     }  
  50. protected:  
  51.     unsigned m_iBufferSize;  
  52.     char* m_pBuffer;  
  53.     int m_iInstanceID;  
  54.     staticint ms_iInstanceCounter;  
  55. };  
  56. int CSomeObject::ms_iInstanceCounter = 0;  
  57. class CSomeObjectWithMoveConstructor : public CSomeObject  
  58. {  
  59. public:  
  60.     CSomeObjectWithMoveConstructor()  
  61.         : CSomeObject()  
  62.     {  
  63.     }  
  64.     // 普通建構函式
  65.     CSomeObjectWithMoveConstructor(unsigned int iBufferSize)  
  66.         : CSomeObject(iBufferSize)  
  67.     {  
  68.     }  
  69.     // 拷貝建構函式
  70.     CSomeObjectWithMoveConstructor(const CSomeObjectWithMoveConstructor& objSource)  
  71.         : CSomeObject(objSource)  
  72.     {  
  73.     }  
  74.     // 轉移建構函式
  75.     CSomeObjectWithMoveConstructor(CSomeObjectWithMoveConstructor&& objSource)  
  76.     {  
  77.         if (g_bTraceOutput)  
  78.             cout << "In MOVE constructor from ID " << objSource.m_iInstanceID << " to ID " << m_iInstanceID << " (size=" << objSource.m_iBufferSize << ")" << endl;  
  79.         m_iBufferSize = objSource.m_iBufferSize;  
  80.         m_pBuffer = objSource.m_pBuffer;  
  81.         objSource.m_iBufferSize = 0;  
  82.         objSource.m_pBuffer = NULL;  
  83.     }  
  84. };  
  85. int _tmain(int argc, _TCHAR* argv[])  
  86. {  
  87.     vector<CSomeObjectWithMoveConstructor> vec1;  
  88.     cout << "Adding first object to vector:" << endl;  
  89.     vec1.push_back(CSomeObjectWithMoveConstructor(1024));  
  90.     cout << endl << "Adding second object to vector:" << endl;  
  91.     vec1.push_back(CSomeObjectWithMoveConstructor(1024));  
  92.     g_bTraceOutput = false;  
  93.     cout << endl << "Press any key to run some timings..." << endl;  
  94.     cin.get();  
  95.     staticint siBufferSize = 1024*1024*10;  
  96.     staticint siObjectCount = 100;  
  97.     // 第一次無轉移建構函式
  98.     cout << "Without move constructor: /t";  
  99.     DWORD dwStart = GetTickCount();  
  100.     vector<CSomeObject> vec2;  
  101.     for (int i=0; i<siObjectCount; ++i)  
  102.     {  
  103.         vec2.push_back(CSomeObject(siBufferSize));  
  104.     }  
  105.     DWORD dwEnd = GetTickCount();  
  106.     cout << "Elapsed time: " << (dwEnd-dwStart) << " milliseconds." << endl;  
  107.     vec2.clear();  
  108.     // 第2次有轉移建構函式
  109.     cout << "With move constructor: /t";  
  110.     dwStart = GetTickCount();  
  111.     vector<CSomeObjectWithMoveConstructor> vec3;  
  112.     for (int i=0; i<siObjectCount; ++i)  
  113.     {  
  114.         vec3.push_back(CSomeObjectWithMoveConstructor(siBufferSize));  
  115.     }  
  116.     dwEnd = GetTickCount();  
  117.     cout << "Elapsed time: " << (dwEnd-dwStart) << " milliseconds." << endl;  
  118.     vec3.clear();  
  119.     return 0;  
  120. }  
#include "stdafx.h"#include <vector>#include <iostream>using namespace std;bool g_bTraceOutput = true;class CSomeObject{public: CSomeObject()  : m_iBufferSize(0)  , m_pBuffer(NULL)  , m_iInstanceID(ms_iInstanceCounter++) { } // 普通建構函式 CSomeObject(unsigned int iBufferSize)  : m_iBufferSize(iBufferSize)  , m_pBuffer(NULL)  , m_iInstanceID(ms_iInstanceCounter++) {  if (g_bTraceOutput)   cout << "In NORMAL constructor for ID " << m_iInstanceID << " (size=" << m_iBufferSize << ")" << endl;  if (m_iBufferSize > 0)  {   m_pBuffer = new char[m_iBufferSize];   memset(m_pBuffer, 0, m_iBufferSize);  } } // 拷貝建構函式 CSomeObject(const CSomeObject& objSource)  : m_iInstanceID(ms_iInstanceCounter++) {  if (g_bTraceOutput)   cout << "In COPY constructor from ID " << objSource.m_iInstanceID  << " to ID " << m_iInstanceID << " (size=" << objSource.m_iBufferSize << ")" << endl;  m_iBufferSize = objSource.m_iBufferSize;  if (m_iBufferSize > 0)  {   m_pBuffer = new char[m_iBufferSize];   memset(m_pBuffer, 0, m_iBufferSize);  } } ~CSomeObject() {  if (g_bTraceOutput)   cout << "In destructor for ID " << m_iInstanceID << " (size=" << m_iBufferSize << ")" << endl;  if (m_pBuffer)   delete [] m_pBuffer;  m_pBuffer = NULL; }protected: unsigned m_iBufferSize; char* m_pBuffer; int m_iInstanceID;  static int ms_iInstanceCounter;};int CSomeObject::ms_iInstanceCounter = 0;class CSomeObjectWithMoveConstructor : public CSomeObject{public: CSomeObjectWithMoveConstructor()  : CSomeObject() { } // 普通建構函式 CSomeObjectWithMoveConstructor(unsigned int iBufferSize)  : CSomeObject(iBufferSize) { } // 拷貝建構函式 CSomeObjectWithMoveConstructor(const CSomeObjectWithMoveConstructor& objSource)  : CSomeObject(objSource) { } // 轉移建構函式 CSomeObjectWithMoveConstructor(CSomeObjectWithMoveConstructor&& objSource) {  if (g_bTraceOutput)   cout << "In MOVE constructor from ID " << objSource.m_iInstanceID << " to ID " << m_iInstanceID << " (size=" << objSource.m_iBufferSize << ")" << endl;  m_iBufferSize = objSource.m_iBufferSize;  m_pBuffer = objSource.m_pBuffer;  objSource.m_iBufferSize = 0;  objSource.m_pBuffer = NULL; }};int _tmain(int argc, _TCHAR* argv[]){ vector<CSomeObjectWithMoveConstructor> vec1; cout << "Adding first object to vector:" << endl; vec1.push_back(CSomeObjectWithMoveConstructor(1024)); cout << endl << "Adding second object to vector:" << endl; vec1.push_back(CSomeObjectWithMoveConstructor(1024)); g_bTraceOutput = false; cout << endl << "Press any key to run some timings..." << endl; cin.get(); static int siBufferSize = 1024*1024*10; static int siObjectCount = 100; // 第一次無轉移建構函式 cout << "Without move constructor: /t"; DWORD dwStart = GetTickCount(); vector<CSomeObject> vec2; for (int i=0; i<siObjectCount; ++i) {  vec2.push_back(CSomeObject(siBufferSize)); } DWORD dwEnd = GetTickCount(); cout << "Elapsed time: " << (dwEnd-dwStart) << " milliseconds." << endl; vec2.clear(); // 第2次有轉移建構函式 cout << "With move constructor: /t"; dwStart = GetTickCount(); vector<CSomeObjectWithMoveConstructor> vec3; for (int i=0; i<siObjectCount; ++i) {  vec3.push_back(CSomeObjectWithMoveConstructor(siBufferSize)); } dwEnd = GetTickCount(); cout << "Elapsed time: " << (dwEnd-dwStart) << " milliseconds." << endl; vec3.clear(); return 0;}

供大家學習vc++2010新特性,歡迎技術交流

c++標準沒有定義臨時物件,但是它假定臨時物件是匿名的,例如函式的返回值。按照我們的更一般化的定義,在函式中定義的命名的棧分配的變數也是臨時的。