C++封裝 之 拷貝建構函式
阿新 • • 發佈:2021-08-25
拷貝建構函式
思考
- 拷貝建構函式的定義?
- 什麼時候呼叫拷貝建構函式?
- 拷貝建構函式如何實現?
拷貝建構函式回顧:
-
定義:
拷貝建構函式與普通建構函式基本相同,只是引數上有嚴格要求:(1)要加const ;(2)傳入的是引用,且是一個物件; -
如果沒有自定義拷貝建構函式,系統會自動生成一個預設的拷貝建構函式。
-
當採用直接初始化(Student st1)或複製初始化(Student st2=st1 或Student st2(st3) )例項化物件時,系統自動呼叫拷貝建構函式;
-
函式呼叫傳遞引數時也會呼叫拷貝建構函式。
-
拷貝建構函式的引數是確定的,不能過載。
淺拷貝 和 深拷貝
- 只是將資料成員的值進行了簡單的拷貝,稱為淺拷貝;
- 不僅僅是做值的拷貝,堆中記憶體也要拷貝,稱為深拷貝。
例項1(淺拷貝)
定義一個Array類
- 資料成員為m_iCount ,
- 成員函式包括建構函式、拷貝建構函式、解構函式、資料封裝函式
- 通過此示例體會淺拷貝原理
copy_demo1.cpp原始碼:
#include<iostream> #include<stdlib.h> using namespace std; /****************** 定義Array類 ******************************/ class Array{ public: Array(); Array(const Array &arr); //拷貝建構函式定義 ~Array(); void setCount(int count); int getCount(); private: int m_iCount; }; /****************** Array類的函式實現 ******************************/ Array::Array(){ cout << "Array()" << endl; } Array::Array(const Array &arr){ //拷貝建構函式實現 m_iCount = arr.m_iCount; cout << "Array &" << endl; } Array::~Array(){ cout << "~Array()" << endl; } void Array::setCount(int count){ m_iCount = count; } int Array::getCount(){ return m_iCount; } /****************** 測試主函式 ******************************/ int main(){ Array arr1; arr1.setCount(9); cout << "arr1.m_iCount = "<< arr1.getCount() << endl; Array arr2(arr1); // 用arr1拷貝例項化arr2,呼叫拷貝建構函式 cout << "arr2.m_iCount = "<<arr2.getCount() << endl; system("pause"); return 0; }
執行結果:
Array()
arr1.m_iCount = 9
Array &
arr2.m_iCount = 9
例項2(深拷貝)
- 增加資料成員m_pArr
- 並增加m_pArr地址檢視函式,同時改造建構函式、拷貝建構函式和解構函式,
- 通過此示例體會淺拷貝原理
copy_demo2.cpp原始碼
#include<iostream> #include<stdlib.h> using namespace std; /****************** 定義Array類 ******************************/ class Array{ public: Array(int count); Array(const Array &arr); //拷貝建構函式定義 ~Array(); void setCount(int count); int getCount(); void printAddr(); //資料成員*m_pArr的封裝函式,列印地址 void printArr(); //列印m_pArr所指向地址的值 private: int m_iCount; int *m_pArr; //增加資料成員*m_pArr }; /****************** Array類的函式實現 ******************************/ Array::Array(int count){ m_iCount = count; m_pArr = new int[m_iCount]; //前提是m_iCount是一個確切的值,所以建構函式要傳入一個引數count for(int i=0; i<m_iCount; i++) //賦值(為了方便列印) m_pArr[i] = i; cout << "Array()" << endl; } /* Array::Array(const Array &arr){ //拷貝建構函式實現(淺拷貝) m_pArr = arr.m_pArr; //兩個指標指向同一塊記憶體(理論上是錯誤的) m_iCount = arr.m_iCount; cout << "Array &" << endl; } */ Array::Array(const Array &arr){ //拷貝建構函式實現(深拷貝) m_iCount = arr.m_iCount; m_pArr = new int[m_iCount]; //先給當前指標分配記憶體 for(int i=0; i<m_iCount; ++i){ //再做記憶體拷貝 m_pArr[i] = arr.m_pArr[i]; } cout << "Array &" << endl; } Array::~Array(){ delete []m_pArr; // m_pArr = NULL; // cout << "~Array()" << endl; } void Array::setCount(int count){ m_iCount = count; } int Array::getCount(){ return m_iCount; } void Array::printAddr(){ /// cout << "m_pArr point to " << m_pArr << endl; } void Array::printArr(){ for(int i=0; i<m_iCount; i++) cout<<"m_pArr["<<i<<"] = "<< m_pArr[i]<<endl; } /****************** 測試主函式 ******************************/ int main(){ Array arr1(9); Array arr2(arr1); // 用arr1拷貝例項化arr2,呼叫拷貝建構函式,使用深拷貝之後,兩個指標指向不同記憶體地址 //arr1.setCount(9); //建構函式中已經傳入了引數9,所以不需要arr1.setCount(9)了 arr1.printAddr(); arr2.printAddr(); //兩個指標會指向同一塊記憶體,同一塊記憶體不能釋放兩遍,兩個物件都執行解構函式就會發生執行時錯誤 arr1.printArr(); arr2.printArr(); system("pause"); return 0; }
執行結果:
Array()
Array &
m_pArr point to 0x711920
m_pArr point to 0x711960
m_pArr[0] = 0
m_pArr[1] = 1
m_pArr[2] = 2
m_pArr[3] = 3
m_pArr[4] = 4
m_pArr[5] = 5
m_pArr[6] = 6
m_pArr[7] = 7
m_pArr[8] = 8
m_pArr[0] = 0
m_pArr[1] = 1
m_pArr[2] = 2
m_pArr[3] = 3
m_pArr[4] = 4
m_pArr[5] = 5
m_pArr[6] = 6
m_pArr[7] = 7
m_pArr[8] = 8