【c++基礎】——構造函數、析構函數以及拷貝構造

寫在前面:
簡單的說:一個對象出生的時候,使用構造函數,死掉的時候,使用析構函數

構造函數 和 析構函數 各有各的用途,在構造函數中,我們來獲取資源;在析構函數中,我們來釋放資源。釋放了之後,這些資源就會被回收,可以被重新利用。
在構造函數裏,我們去連接數據庫的連接,在析構函數裏關閉數據庫的連接。
在構造函數裏動態的分配內存,那麼在析構函數裏把動態分配的內存回收。

簡單區分:

特點 構造函數 析構函數
對應對象的階段 出生 死亡
主要直觀區別 獲取資源(動態內存,連接等) 釋放資源(動態內存,連接等)
作用 建立標識符、開闢內存、 數據成員的初始化 對象撤銷是的清理作用
特點 (1)與類名通名字比如Point();(2)無返回類型以及返回值;(3)不能被顯式調用;(4)對象被創建時自動執行 (1)類名同名~Point(),但是要在前面加一個~;(2)可以被顯式的調用, 以釋放對象中動態申請的內存

構造函數

  • 概念:類的構造函數是類的一種特殊的成員函數,它會在每次創建類的新對象時執行

  • 作用:
    ■ 給創建的對象建立一個標識符;
    ■ 爲對象數據成員開闢內存空間;
    ■ 完成對象數據成員的初始化

  • 默認構造函數
    當用戶沒有顯式的去定義構造函數時, 編譯器會爲類生成一個默認的構造函數, 稱爲 “默認構造函數”, 默認構造函數不能完成對象數據成員的初始化, 只能給對象創建一標識符, 併爲對象中的數據成員開闢一定的內存空間。也就是少了上面三個作用中的最後一個作用初始化!

  • 特點:
    無論是用戶自定義的構造函數還是默認構造函數都主要有以下特點:
    ①. 在對象被創建時自動執行;
    ②. 構造函數的函數名與類名相同;
    ③. 沒有返回值類型、也沒有返回值;
    ④. 構造函數不能被顯式調用。

  • 顯示構造函數:
    我們需要顯式定義一個構造函數來覆蓋掉默認構造函數以便來完成必要的初始化工作, 當用戶自定義構造函數後編譯器就不會再爲對象生成默認構造函數

  • 有參數的構造函數:
    有時候在創建時每個對象的屬性有可能是不同的, 這種直接賦值的方式顯然不合適。不過構造函數是支持向函數中傳入參數的, 所以可以使用帶參數的構造函數來解決該問題

  • 構造函數的重載
    構造函數也畢竟是函數, 與普通函數相同, 構造函數也支持重載, 需要注意的是, 在進行構造函數的重載時要注意重載和參數默認的關係要處理好, 避免產生代碼的二義性導致編譯出錯

  • 初始化表達式
    對象中的一些數據成員除了在構造函數體中進行初始化外還可以通過調用初始化表來進行完成, 要使用初始化表來對數據成員進行初始化時使用 : 號進行調出, 示例如下:

      Point(int x = 0, int y = 0):xPos(x), yPos(y)  //使用初始化表
      {
          cout<<"調用初始化表對數據成員進行初始化!\n";
      }
    

    在 Point 構造函數頭的後面, 通過單個冒號 : 引出的就是初始化表, 初始化的內容爲 Point 類中int型的 xPos 成員和 yPos成員, 其效果和 xPos = x; yPos = y; 是相同的。

    與在構造函數體內進行初始化不同的是, 使用初始化表進行初始化是在構造函數被調用以前就完成的。每個成員在初始化表中只能出現一次, 並且初始化的順序不是取決於數據成員在初始化表中出現的順序, 而是取決於在類中聲明的順序。

    此外, 一些通過構造函數無法進行初始化的數據類型可以使用初始化表進行初始化, 如: 常量成員和引用成員, 這部分內容將在後面進行詳細說明。使用初始化表對對象成員進行初始化的完整示例:

https://www.cnblogs.com/mr-wid/archive/2013/02/19/2917911.html
https://blog.csdn.net/github_35160620/article/details/52602332

析構函數

  • 概念:類的一種特殊的成員函數,它會在每次刪除所創建的對象時執行
    與構造函數相反, 析構函數是在對象被撤銷時被自動調用, 用於對成員撤銷時的一些清理工作, 例如在前面提到的手動釋放使用 new 或 malloc 進行申請的內存空間

  • 特點:
    ■ 析構函數函數名與類名相同, 緊貼在名稱前面用波浪號 ~ 與構造函數進行區分, 例如: ~Point();
    ■ 構造函數沒有返回類型, 也不能指定參數, 因此析構函數只能有一個, 不能被重載;
    ■ 當對象被撤銷時析構函數被自動調用, 與構造函數不同的是, 析構函數可以被顯式的調用, 以釋放對象中動態申請的內存。

  • 默認析構函數
    當用戶沒有顯式定義析構函數時, 編譯器同樣會爲對象生成一個默認的析構函數, 但默認生成的析構函數只能釋放類的普通數據成員所佔用的空間, 無法釋放通過 new 或 malloc 進行申請的空間, 因此有時我們需要自己顯式的定義析構函數對這些申請的空間進行釋放, 避免造成內存泄露。

拷貝構造——暫時不太明白!

  • 就類對象而言,相同類型的類對象是通過拷貝構造函數來完成整個複製過程的。

  • 概念:拷貝構造函數是一種特殊的構造函數,它在創建對象時,是顯示或隱式樣的使用同一類中之前創建的對象來初始化新創建的對象

  • 作用:
    ■通過使用另一個同類型的對象來初始化新創建的對象。
    ■複製對象把它作爲參數傳遞給函數。
    ■複製對象,並從函數返回這個對象。

  • 如果在類中沒有定義拷貝構造函數,編譯器會自行定義一個。如果類帶有指針變量,並有動態內存分配,則它必須有一個拷貝構造函數。

還可以參考這個:https://blog.csdn.net/wenqiang1208/article/details/52851633講的也不錯

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章