1. 程式人生 > >C++預設函式與深淺拷貝

C++預設函式與深淺拷貝

形參與實參

形參:是函式宣告時的引數,只說明引數名和型別,不是實際的引數,不能真正使用。

實參:執行時傳給函式的引數,是實際的變數,形參在這時真正地被分配空間,並且賦值了實參的值。

一個函式的實參在記憶體中有自己固定的記憶體,直到函式執行結束才釋放記憶體。而形參沒有固定的記憶體,只在呼叫函式的時候有一個虛擬記憶體,等呼叫完畢就不再有記憶體。他們的關係是函式呼叫的時候,實參把值傳給形參

建構函式

(1)建構函式不能有返回值,函式名為類名

(2)預設建構函式時,系統將自動呼叫該預設建構函式初始化物件,預設建構函式會將所有資料成員都初始化為0或者空。預設建構函式是不帶引數的

(3)建立一個物件時,系統自動呼叫建構函式

解構函式

解構函式沒有引數和返回值。不能過載,一個類中只能定義一個解構函式,如果一個類中沒有定義解構函式,系統會自動生成一個預設的解構函式,為空函式,什麼都不做。呼叫條件:

(1)在函式體內定義的物件,當函式執行結束時,該物件所在類的解構函式會被自動呼叫。(在一個函式中定義一個物件,當函式呼叫結束,則會自動呼叫解構函式來刪除在這個函式體內建立的物件,包括主函式。)

(2)用new運算子動態構造的物件,在使用delete運算子釋放它時。

拷貝建構函式

拷貝建構函式實際上也是建構函式,具有一般建構函式的所有特性,其名字也與所屬類名相同。拷貝建構函式中只有一個引數,這個引數是對某個同類物件的引用。

(1)用類的一個已知物件去初始化該類的另一個物件時。(初始化時A = B,也可以用A(B))

(2)函式的形參是類的物件,呼叫函式進行形參和實參的結合時。(定義一個函式A,A函式的形參是類的物件,在另外一個函式B中呼叫這個函式A,實參將具體的物件傳遞給形參,這時候會呼叫拷貝建構函式。)

(3)函式的返回值是類的物件,函式執行完返回呼叫者。(定義一個函式A,該函式的返回值是一個類的物件,在函式B中定義類的物件來接受函式A的返回,這時會呼叫拷貝建構函式。)

淺拷貝

所謂淺拷貝是指在物件複製時,只是對物件中的資料成員進行簡單的賦值,這就是淺拷貝,預設的拷貝建構函式執行的也是淺拷貝。大多數情況之下“淺拷貝”能很好的工作,但是一旦物件存在了動態成員,那麼淺拷貝就會出問題。

1、淺拷貝的應用

(1)拷貝建構函式

class A

{

     char *p;

     int len;

};

A obj2 = obj1;//呼叫obj2的拷貝建構函式Class(Class &other)

如果沒有定義拷貝建構函式,就會呼叫C++自帶的拷貝建構函式,此時:obj1的成員變數p和len都在棧區,p指標存放的是地址資訊,指向堆中的資料(全域性變數區複製過來的,注意:全域性變數區和堆區都有這部分資料)。而C++自帶的拷貝建構函式,執行了淺拷貝,只是在棧區把p和len複製了一份給obj2,故p也指向堆中的資料區域。在兩個變數生命週期結束,需要析構時,obj2正常析構,資料析構,指標為NULL,obj1中的p就成了野指標。

(2)等號操作符

A obj1("A1");

A obj2("A2");

obj2 = obj1;//如果不自己過載operator = (),則呼叫C++自己的=操作符進行p和len的簡單值拷貝,指標所指的堆中區域沒有拷貝,obj1和obj2中的指標p指向堆中相同區域的資料。

 

 

深拷貝

在“深拷貝”下,對於物件中動態成員,就不能僅僅簡單的賦值了,而是應該重新動態分配空間。

總結:

拷貝建構函式分為深拷貝和淺拷貝,一般情況之下淺拷貝已經滿足要求,但是當存在動態成員時,淺拷貝就不能滿足需求了。比如一個物件中有指標成員,只是通過簡單的淺拷貝,只能讓複製的物件指向同一片區域,而不是建立一片同樣大小的區域,這就需要通過深拷貝來解決。

參考:http://blog.csdn.net/bluescorpio/article/details/4322682