天天看點

一文帶你學習C++析構函數

作者:音視訊開發老舅

C++析構函數的學習

在C++中,析構函數是一種特殊類型的成員函數,用于在對象生命周期結束時被自動調用。一個對象生命周期的終止可以發生在以下情況:

  • 函數執行完畢
  • 對象被顯式删除
  • 對象超出範圍

在這些情況下,析構函數都會被調用,該函數負責清除對象占用的記憶體空間和釋放其他資源。析構函數的文法如下:

class ClassName {
public:
    ClassName(); // 構造函數
    ~ClassName(); // 析構函數
};           

可以看到,在類中聲明析構函數時,在函數名前加上了一個波浪線符号“~”,這用來表示這是一個析構函數。與構造函數一樣,析構函數也可以被重載

接下來,我們将介紹C++析構函數的一些重要知識點,并提供相應代碼示例

析構函數的基本使用

當構造函數建立一個對象時,它使用new運算符配置設定記憶體。在對象不再需要時,我們需要使用delete運算符來釋放記憶體。在這種情況下,析構函數就可以派上用場。下面是一個簡單的示例:

#include<iostream> 
using namespace std; 

class Number {
private:
    int* ptr;
public:
    Number() {
        ptr = new int;
        *ptr = 0;
    }
  
    ~Number() {
        delete ptr;
    }
  
    int getValue() {
        return *ptr;
    }
    
    void setValue(int value) {
        *ptr = value;
    }
};

int main() {
    Number obj1;

    obj1.setValue(5);
    cout << obj1.getValue() << endl;

    return 0;
}           

在這個示例中,我們使用了一個指向整數的指針,并在構造函數中為其配置設定記憶體。在析構函數中,我們使用delete運算符來釋放該指針的記憶體空間。這個程式列印出5,表明成功對obj1中的整數值進行了修改

領C++資料→「連結」

多個析構函數的使用

如果在類中定義了多個析構函數,無論是因為函數重載,還是出于其他原因,它們都會按照與它們的構造函數相同的順序被自動調用 ,下面是一個示例:

#include<iostream> 
using namespace std; 

class Student {
private:
    int age;
    char* name;
public:
    Student() {
        age = 0;
        name = new char[10];
    }

    Student(int a, char* n) {
        age = a;
        name = new char[strlen(n) + 1];
        strcpy(name, n);
    }
  
    ~Student() {
        delete [] name;
    }

    void display() {
        cout<<"Name: "<<name<<" Age: "<<age<<endl;
    }
};

int main() {
    Student obj1(19, "John");
    Student obj2(21, "Peter");
    obj1.display();
    obj2.display();

    return 0;
}           

在這個示例中,我們定義了兩個構造函數,一個預設的和一個帶參數的。當我們建立兩個對象時,分别使用了這兩個不同的構造函數。在析構函數中,我們釋放了為name指針配置設定的記憶體空間,而不管哪個構造函數被使用,這樣就避免了記憶體洩露

繼承中的析構函數

在繼承中,基類的析構函數會在派生類的析構函數之前被自動調用,是以必須在基類中定義一個虛析構函數。這允許派生類中的任何資源在析構之前被清理。下面是一個示例:

#include<iostream> 
using namespace std; 

class Shape {
public:
    Shape() {
        cout<<"Shape constructor\n";
    }
  
    virtual ~Shape() {
        cout<<"Shape destructor\n";
    }
};

class Square: public Shape {
public:
    Square() {
        cout<<"Square constructor\n";
    }
  
    ~Square() {
        cout<<"Square destructor\n";
    }
};

int main() {
    Shape* shape = new Square();
    delete shape;

    return 0;
}           

在這個示例中,我們定義了一個Shape基類和一個Square派生類。由于Shape類定義了虛拟析構函數,當我們通過基類指針delete Square對象時,它将首先調用Shape類的析構函數,然後再調用Square類的析構函數,確定派生類中的任何資源被清理

總結

在本文中,介紹了C++析構函數的基本知識點,包括在記憶體配置設定和釋放、多個析構函數的使用和繼承中的析構函數。強調了析構函數負責清理對象占用的記憶體空間和釋放其他資源,在對象的生命周期結束時被自動調用

需要注意的是,在使用析構函數時,必須確定不會在它們已被調用的對象上進行任何操作,否則可能會出現嚴重的程式設計錯誤。另外,在使用多個析構函數時,它們的順序非常重要,應該按照構造函數的順序進行調用

繼續閱讀