C++復制構造函數,類型轉換構造函數,析構函數,引用,指針常量和常量指針


復制構造函數
形如className :: className(const &)   /   className :: className(const className &)后者能以常量對象作為參數
如不寫復制構造函數,則編譯器默認提供,為了完成對象的復制功能

它起作用有三個工作環境:

1.一個對象初始化另一個同類的對象

1 Simple c2(c1); 2 Simple c2 = c1;//初始化

2.如果某函數有一個參數是類的一個對象,那么該函數被調用時,類的復制構造函數被調用

 1 Simple A  2 {  3  pbulic:  4  A(){};  5     A(A & a)  6  {  7         cout<<.....<<endl;  8  }  9 }; 10 void Fun(A a1){} 11 int main() 12 { 13  A a; 14     Fun(a);//.....
15     return 0; 16 }

3.如果函數的返回值是類的對象時,則函數返回是,類的復制構造函數被調用

 1 class Simple  2 {  3  pbulic:  4         int x;  5         Simple(int n){x = n;};  6         Simple(const Simple & a)  7  {  8             x = a.x;  9             cout<<"Copy constructor called"<<endl; 10  } 11 }; 12 Simple Fun() 13 { 14     Simple b(100); 15     return b;//作為復制構造函數的參數
16 } 17 int main() 18 { 19     cout<<Fun().x<<endl;// Copy constructor called 100
20     return 0; 21 }

注意:對象間的賦值不導致復制構造函數的調用

A c1,c2;
c2 = c1 ;//不會調用
A C3(C1);//這是初始化操作,會調用賦值構造函數

在函數參數列表中,為節省開銷,不引發復制構造函數的調用,使用ClassName & 引用類型為參數,
又為了確保實參值不變,再在引用前加上const關鍵字。復制構造函數往往加const和&,具體可以點這里


類型轉換構造函數

它的目的是實現類型的自動轉換,並且只有一個參數。當需要的時候,編譯系統會自動調用轉換構造函數,建立

一個無名的臨時對象(或臨時變量)。

 1 class Complex  2 {  3 public:  4     double real, imag;  5     Complex( int i)  6     {//類型轉換構造函數
 7         cout << "IntConstructor called" << endl;  8     real = i; imag = 0;  9  } 10     Complex(double r,double i) {real = r; imag = i; } 11 }; 12 int main () 13 { 14     Complex c1(7,8); 15     Complex c2 = 12; 16     c1 = 9; // 9被自動轉換成一個臨時Complex對象
17     cout << c1.real << "," << c1.imag << endl; 18     return 0; 19 }            
 1 class Complex  2 {  3 public:  4     double real, imag;  5     explicit Complex( int i)  6     {//顯式類型轉換構造函數
 7         cout << "IntConstructor called" << endl;  8         real = i; imag = 0;  9  } 10     Complex(double r,double i) {real = r; imag = i; } 11 }; 12 int main () 13 { 14     Complex c1(7,8); 15     Complex c2 = Complex(12); 16     c1 = 9; // error, 9不能被自動轉換成一個臨時Complex對象
17     c1 = Complex(9) //ok
18     cout << c1.real << "," << c1.imag << endl; 19     return 0; 20 }

 析構函數:~類名(){}

它沒有返回值和參數,一個類對應一個析構函數,在類的對象消亡時自動調用,也可以手動調用進行對象消亡的善后工作。如果懶的去寫,編譯器自動會生成缺省析構函數,但是什么也不做,如果寫了,就不自動生成了

 1 class Simple  2 {  3 private :  4     char * p;  5 public:  6  Simple()  7  {  8         p = new char[10];  9  } 10     ~ Simple () ; 11 }; 12 Simple ::~ Simple() 13 { 14     delete [] p; 15 }

在對一個對象進行delete時,調用一次析構函數,在delete[]對象數組時,會調用n次析構函數,取決於數組大小。此外:

 1 class CMyclass  2 {  3 public:  4     ~CMyclass() { cout << "destructor" << endl; }  5 };  6 CMyclass obj;  7 CMyclass fun(CMyclass sobj )  8 { //參數對象消亡也會導致析  9 //構函數被調用
10     return sobj; //函數調用返回時生成臨時對象返回
11 } 12 int main() 13 { 14     obj = fun(obj); //函數調用的返回值(臨時對象)被
15     return 0; //用過后,該臨時對象析構函數被調用
16 } 17 //destructor形參對象消亡 18 //destructor臨時對象消亡 19 //destructor全局對象消亡

new出來的對象或對象數組,不delete就不會消亡,就不會調用析構函數!!不是new出來的,則在生命期結束會自動調用


 關於引用:引用是C++有的,C所沒有的,標志為 &,即C的取地址符。它的聲明為這樣

1 int n = 4; 2 int & r = n; //r為 int & 類型 

其中r和n指向同一片地址空間 ,對 r和n的修改都會改變原來是4的那個值,相當於為n取了個別名r

在定義引用時一定要將其初始化成引用某個變量。並且之后不會引用別的變量
只能引用變量,不能引用常量和表達式

一個簡單而又形象的,見得次數很多的例子:交換元素

1 void swap( int * a, int * b) 2 { 3     int tmp; 4     tmp = * a; 5     * a = * b; 6     * b = tmp; 7 } 8 int n1, n2; 9 swap(& n1,& n2) ; // n1,n2的值被交換
 1 //用了引用  2 void swap( int & a, int & b)  3 {  4     int tmp;  5     tmp = a;  6     a = b;  7     b = tmp;  8 }  9 int n1, n2; 10 swap(n1,n2) ; // n1,n2的值被交換
 1 //en ..交換還可以這樣寫,當然遠不如swap(a,b)寫的快哈
 2     int a = 3;  3     int b = 5;  4     a = a + b;  5     b = a - b;  6     a = a - b;  7     cout<<a<<" "<<b<<endl;  8     a = a ^ b;  9     b = a ^ b; 10     a = a ^ b; 11     cout<<a<<" "<<b<<endl;

引用還可以作為函數的返回值

 1 int n = 4;  2 int & SetValue()  3 {  4     return n;  5 }  6 int main()  7 {  8     SetValue() = 40;  9     cout << n;return 0; 10 } //輸出: 40

 關於常引用

int n;
const int & r = n;
r = 10;//error 不能通過常引用r改變n的值
n = 30;//n的值可以變化
const T & 和T & 是不同的類型!!!
T & 類型的引用T類型的變量可以用來初始化const T & 類型的引用
int n = 8;
int & r1 = n;
const int r2 = r1;//初始化const T & 類型的引用。
const T 類型的常變量和const T & 類型的引用則不能用來初始化T &類型的引用,
除非進行強制類型轉換


 常量指針

 1 //1.
 2 int n,m  3 const int * p = n;//常量指針
 4 *p = 5//error 不可以通過修改常量指針修改指向的內容
 5 n = 5;//ok
 6 p = & m;//ok 常量指針可以指向別的內容  7 
 8 //2.不可以把常量指針賦值給非常量指針(強轉可以),反之可以
 9 const int * p; 10       int * p2; 11 p1 = p2; //ok
12 p2 = p1; //error
13 p2 = (int * ) p1; //ok,強制類型轉換

指針常量

1 int a,b; 2 int const *p = & a; 3 * p = 9;//通過指針修改所指向的內容,ok
4 p = & b;//error 不可更改所指向的地址

這兩個不要搞混淆了。。。。

簡單的記憶,抓住第一個是常量在前,就意味着整個后面的地址內容是個常量,不可以通過指針去修改它,但是指向誰是可以變的;指針常量,這個常量在指針后面,表明這個指針所指向的地址不能變了,但你可以用它修改地址所對應的內容。


 動態內存分配:

變量: int * px = new int; //大小為sizeof(int)
數組: int * pn = new int[20];
釋放動態分配的內存:
int * px = new int;
delete px;//只能刪除一次
//數組
int * pn = new int[20];
delete [] pn;

 


免責聲明!

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



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