//overload2.h中 class NumberArray { private: double *aPtr; int arraySize; public: //複製賦值和複製建構函式 NumberArray& operator=(const NumberArray &right); NumberArray(const NumberArray &); //預設建構函式和常規建構函式 NumberArray(); NumberArray(int size, double value); //解構函式 ?NumberArray(〉 { if(arraySize > 0) delete [ ] aPtr; } void print() const; void seValue(double value); }該類的每個物件都擁有資源,也就是一個指向動態分配記憶體的指標。像這樣的類需要程式設計師定義的複製建構函式和過載的複製賦值運算子,這些都是很有必要的,如果沒有它們,那麼按成員複製操作時將出現對資源的無意共用從而導致傳送錯誤。
NumberArray::NumberArray(const NumberArray &obj) { cout <<"Copy constructor runningn"; arraySize = obj.arraySize; aPtr = new double[arraySize]; for(int index = 0; index < arraySize; index++) { aPtr[index] = obj.aPtr[index]; } }同樣地,也可以將以下語句新增到解構函式、其他建構函式以及複製賦值運算子:
cout <<"Destructor runningn"; cout <<"Default constructor runningn"; cout <<"Regular constructor runningn"; cout <<"Assignment operator runningn";下面的程式演示了複製建構函式和複製賦值運算子的工作方式。
// This program demonstrates the copy constructor and the // copy assignment operator for the NumberArray class. #include <iostream> #include "overload2.h" using namespace std; //Function Prototype NumberArray makeArray(); int main() { NumberArray first; first = makeArray(); NumberArray second = makeArray(); cout << endl << "The objectTs data is "; first.print(); cout << endl; return 0; } //Creates a local object and returns it by value. NumberArray makeArray() { NumberArray nArr(5, 10.5); return nArr; }程式輸出結果:
(1) Default constructor running
(2) Regular constructor running
(3) Copy constructor running
(4) Destructor running
(5) Copy Assignment operator running
(6) Destructor running
(7) Regular constructor running
(8) Copy constructor running
(9) Destructor running
(10) The objecfs data is 10.5010.5010.5010.5010.50
(11) Destructor running
(12) Destructor running
first = makeArray();
它呼叫了複製賦值運算子以複製臨時物件 makeArray(),如輸出結果中的第(5)行所示。複製賦值運算子將刪除 first 中的 aPtr 陣列,分配另外一個陣列,其大小和臨時物件中的大小一樣,然後將臨時陣列中的值複製到 first 的 aPtr 陣列中。NumberArray& NumberArray::operator=(NumberArray&& right) { if (this != &right) { swap(arraySize, right.arraySize); swap(aPtr, right.aPtr); } return *this; }請注意,該函數的原型和複製賦值的原型類似,但是移動賦值釆用了右值參照作為形參。這是因為移動賦值應該僅在賦值的來源是一個臨時物件時才執行。還需要注意的是,移動賦值的形參不能是 const,這是因為它需要通過修改物件 "移動" 資源。
NumberArray::NumberArray(NumberArray && temp) { //從temp物件中“竊取”資源 this->arraySize = temp.arraySize; this->aPtr = temp.aPtr; //將temp放置到安全狀態以防止其解構函式執行 temp.arraySize = 0; temp.aPtr = nullptr; }請注意,移動建構函式的形參也不能是 const。此外,作為移動建構函式獲取資源來源 的臨時物件必須放置到安全狀態,使得其解構函式可以正常執行而不會導致出錯。
//overload3.h 的內容 #include <iostream> using namespace std; class NumberArray { private: double *aPtr; int arraySize; public: //Copy assignment and copy constructor NumberArrays operator=(constNumberArray &right); NumberArray(constNumberArray &); //Default constructor and Regular constructor NumberArray; NumberArray(int size, double value); //Move Assignment and Move Constructor NumberArrays operator=(NumberArray &&); NumberArray (NumberArray &&); // Destructor ?NumberArray(); void print () const; void setValue(double value); }; //overload3.cpp 的內容 #include <iostream> #include "overload3.h" using namespace std; NumberArray&NumberArray::operator=(const NumberArray&right) { cout <<"Copy Assignment operator runningn"; if (this != &right) { if (arraySize > 0) { delete [ ] aPtr; } arraySize = right.arraySize; aPtr = new double[arraySize]; for (int index = 0; index < arraySize; index++) { aPtr[index] = right.aPtr[index]; } } return *this; } NumberArray::NumberArray(const NumberArray&obj) { cout <<"Copy constructor runningn"; arraySize = obj.arraySize; aPtr = new double[arraySize]; for (int index = 0; index < arraySize; index++) { aPtr[index] = obj.aPtr[index]; } } NumberArray::NumberArray(int size1, double value) { cout << "Regular constructor runningn"; arraySize = Size1; aPtr = new double[arraySize]; setValue(value); } NumberArray::NumberArray() { cout <<"Default constructor runningn"; arraySize = 2; aPtr = new double[arraySize]; setValue (0.0); } void NumberArray::setValue(double value) { for (int index = 0; index < arraySize; index++) { aPtr[index] = value; } } void NumberArray::print()const { for (int index = 0; index < arraySize; index++) { cout << aPtr [index] = " "; } } NumberArray::?NumberArray() { cout <<"Destructor runningn"; if (arraySize > 0) { delete[] aPtr; } } NumberArray &NumberArray::operator(NumberArray&& right) { cout << "Move assignment is runningn"; if (this != &right) { swap(arraySize, right.arraySize); swap(aPtr, right.aPtr); } return *this; } NumberArray::NumberArray(NumberArray && temp) { //從temp物件中“竊取”資源 this->arraySize = temp.arraySize; this->aPtr = temp.aPtr; //將temp放置到安全狀態 //以防止其解構函式執行 temp.arraySize = 0; temp.aPtr = nullptr; }下面的程式中演示了這些操作:
// This program demonstrates move constructor the move assignment operator. #include <iostream> #include "Toverload3.h" using namespace std; NumberArray makeArray();// Prototype int main() { NumberArray first; first = makeArray(); NumberArray second = makeArray(); cout << endl << "The object's data is "; first.print(); cout << endl; return 0; } NumberArray makeArray() { NumberArray nArr(5,10.5); return nArr; }程式輸出結果:
(1) Default constructor running
(2) Regular constructor running
(3) Destructor running
(4) Move assignment is running
(5) Destructor running
(6) Regular constructor running
(7) Destructor running
(8) The objectTs data is10.5010.5010.5010.5010.50
(9) Destructor running
(10) Destructor running