構造函數和析構函數
分類
按照參數分類:有參構造 無參構造(默認構造)
按照類型分類:普通構造 拷貝構造 格式:類名(const 類名 & aaa)
【注】構造函數的寫法(就是一個初始化的函數):
//沒有返回值,也不寫void,函數名與類名相同;
//可以有參數,可以發生重載;
//由編譯器自動調用,不需要手動調用,且編譯器只調用一次;
【注】析構函數的寫法(個人覺得就是銷毀的函數)
//沒有返回值,也不寫void,函數名與類名相同,在函數名前加 ~
//不可以有參數,不能發生重載;
//由編譯器自動調用,不需要手動調用,且編譯器只調用一次;
個人覺得構造函數和析構函數就像是數據結構中鍊表的初始化和銷毀兩個操作,我之前根本不知道這個東西,所以肯定也沒用過,原因是大部分時候這三個函數由編譯器自動添加,不過對於特殊的class,可能需要手寫。
2. 調用
默認構造調用Person p;不要寫成Person p(),編譯器會認為是函數聲明
括號法 Person p1(10) Person p2(p1)
3. 顯示法
Person(10) 匿名函數對象 特點:此行執行完後系統立刻回收
Person(p1) 不可以用拷貝構造來初始化 匿名對象,編譯器認為是對象聲明
隱式法
Person p1 = 10; 相當於編譯器將代碼轉為Person p1=Person(10);
拷貝構造
使用一個已經創建好的對象來初始化另一個對象
以傳值的方式 給函數傳遞參數 void doWord(Person p);
以值的方式返回局部對象 Person doWork();
平時我們常用到拷貝函數而不知道,因為拷貝函數默認是編譯器提供的,我們沒注意到。例如:我們在主函數中定義int a = 10;而將a作為參數傳給子函數,我們都知道在子函數中對a作修改不能影響到主函數中a的值,原因就在於執行時調用了拷貝函數,將a拷貝了一份,而子函數中修改的就是拷貝出來的值。
構造函數的調用規則
系統會默認給一個類添加至少三個函數,默認構造函數,析構函數,拷貝構造函數
如果提供有參構造、系統就不會提供默認構造。但是會提供拷貝構造
如果提供拷貝構造,其他構造函數系統都不提供了
深拷貝和淺拷貝
系統提供拷貝構造函數,只會做簡單的值拷貝
如果類中有屬性開闢到堆區,那麼釋放時,由於淺拷貝問題導致堆區內容重複釋放, 程序down掉
利用深拷貝來解決淺拷貝問題
初始化列表
構造函數名稱 ():屬性(值),屬性(值),屬性(值)······
類對象作為類成員
當其他類對象作為本類成員,先構造其它類對象,再構造自身,釋放時順序與構造
時相反
explicit關鍵字
explicit關鍵字用途:防止隱式類型轉換方式來初始化對象
new 和 delete操作符與malloc() free()函數區別
new delete是運算符 ; malloc() free()是一個庫函數
malooc()返回值是void* ;new返回值是new的對象的指針
malloc()需要判斷是否開闢成功,而new內部做好了操作
malloc()不會調用構造函數 new調用構造函數;
malloc()釋放用free() new釋放用delete;
不要用void* 去接收new出來的對象,會導致不能釋放
利用new在堆區創建數組,類中必須要存在默認構造函數,否則無法創建
如果是數組 釋放時要在 delete後加[]
delete [] person;