Visual Studio2010新特性--C++王者歸來(3-泛型程式設計-轉移建構函式
阿新 • • 發佈:2018-12-19
泛型程式設計(generic programming)關注於產生通用的軟體元件,讓這些元件在不同的應用場合都能很容易地重用。在c++中,類模板和函式模板是進行泛型程式設計極為有效的機制。
什麼是臨時物件?定義:當且僅當離開一段上下文(context)時在物件上執行的僅有的操作是解構函式時,一個物件被看成是臨時的。這裡上下文可能是一個表示式,也可能是一個語句範圍,例如函式體。
建立、複製和銷燬臨時物件是vc++編譯器乾的最多的事情,但臨時物件會降低效能.轉移建構函式就是解決C++存在的不必要的複製問題的方法。
物件生成器物件生成器是一種函式模板,依據其引數產生新的物件。可以把它想象成泛型化的建構函式。有些情況下,欲生成的物件的精確型別很難甚至根本無法表示出來,這時物件生成器可就管用了。物件生成器的優點還在於它的返回值可以直接作為函式引數,而不像建構函式那樣只有在定義變數時才會呼叫。移動構函式就是為了解決C++存在的不必要的複製問題的方法。
VC++2010在c++語言裡面增加了一個特殊的新特性,轉移建構函式,解決C++存在的不必要的複製問題的方法。
程式碼由vc++2010除錯通過!備有詳細的註釋![cpp] view plain copy print?- #include "stdafx.h"
- #include <vector>
- #include <iostream>
- usingnamespace 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 "
- if (m_iBufferSize > 0)
- {
- m_pBuffer = newchar[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 = newchar[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;
- staticint 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();
- staticint siBufferSize = 1024*1024*10;
- staticint 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++標準沒有定義臨時物件,但是它假定臨時物件是匿名的,例如函式的返回值。按照我們的更一般化的定義,在函式中定義的命名的棧分配的變數也是臨時的。