天天看點

C++:預設生成類成員函數詳解

作者:零壹問道

關于C++預設生成的函數的詳細解析及示例說明:

1. 預設構造函數(Default Constructor)

預設構造函數是指在沒有給對象提供初始化參數的情況下,用于建立該類型對象的構造函數。當類中沒有定義任何構造函數時,編譯器會預設生成一個預設構造函數。

示例代碼:

class MyClass {
public:
    int num;
};
MyClass obj; // 調用預設構造函數           

以上代碼中,`MyClass` 類中沒有定義任何構造函數,是以編譯器會自動生成一個預設構造函數 `MyClass::MyClass()`。當我們建立 `MyClass` 類型的對象 `obj` 時,就會自動調用預設構造函數進行對象的初始化。

2. 拷貝構造函數(Copy Constructor)

拷貝構造函數是指用于從一個同類對象初始化另一個同類對象的構造函數。當類中沒有定義任何拷貝構造函數時,編譯器會預設生成一個。

示例代碼:

class MyClass {
public:
    int num;
  
    // 自定義構造函數
    MyClass(int value) {
        num = value;
    }
};

MyClass obj1(20); // 調用自定義構造函數
MyClass obj2(obj1); // 調用拷貝構造函數           

以上代碼中,當我們建立 `MyClass` 類型的對象 `obj2` 時,給定的初始化參數是 `obj1`,是以會調用拷貝構造函數進行對象的初始化。由于我們沒有顯式定義拷貝構造函數,是以編譯器會自動生成一個預設的拷貝構造函數。

3. 指派運算符(Assignment Operator)

指派運算符是用于将一個對象的值賦給另一個對象的運算符。當類中沒有定義任何指派運算符時,編譯器會預設生成一個。預設的指派運算符隻是簡單地逐一複制成員變量的值。

示例代碼:

class MyClass {
public:
    int num;
};

MyClass obj1, obj2;
obj1.num = 10;
obj2 = obj1; // 調用指派運算符           

以上代碼中,當我們将 `obj1` 指派給 `obj2` 時,編譯器會自動生成一個預設的指派運算符 `MyClass::operator=(const MyClass& other)` 進行對象的指派操作。

4. 析構函數(Destructor)

析構函數是用于釋放對象占用資源的函數,它在對象生命周期結束時被調用。當類中沒有定義任何析構函數時,編譯器會預設生成一個空析構函數。

示例代碼:

class MyClass {
public:
    ~MyClass() {
        // 釋放占用的資源
    }
};

MyClass obj;           

以上代碼中,當對象 `obj` 被銷毀時,會自動調用預設的析構函數 `MyClass::~MyClass()` 釋放占用的資源。

5. 移動構造函數(Move Constructor)

移動構造函數是 C++11 中新增的函數,用于在對象間進行資源的轉移。當類中沒有定義任何移動構造函數時,編譯器會預設生成一個。

示例代碼:

class MyClass {
public:
    char* buffer;
  
    // 自定義構造函數
    MyClass(const char* str) {
        buffer = new char[strlen(str) + 1];
        strcpy(buffer, str);
    }
  
    // 移動構造函數
    MyClass(MyClass&& other) noexcept {
        buffer = other.buffer;
        other.buffer = nullptr;
    }

    // 析構函數
    ~MyClass() {
        delete[] buffer;
    }
};

MyClass obj1("abcdefg");          // 調用自定義構造函數
MyClass obj2(std::move(obj1)); // 調用移動構造函數           

以上代碼中,我們定義了一個 `MyClass` 類,其中包括自定義構造函數、移動構造函數和析構函數。在建立對象 `obj1` 時,會調用自定義構造函數為對象配置設定記憶體并初始化資料。接着,我們将 `obj1` 移動給 `obj2`,會調用預設生成的移動構造函數,将對象的資源進行轉移。最後,我們在程式結束時會自動調用析構函數釋放對象占用的記憶體。

6. 移動指派運算符(Move Assignment Operator)

移動指派運算符是 C++11 中新增的運算符,用于在對象間進行資源的轉移。當類中沒有定義任何移動指派運算符時,編譯器會預設生成一個。

示例代碼:

class MyClass {
public:
    char* buffer;
  
    // 自定義構造函數
    MyClass(const char* str) {
        buffer = new char[strlen(str) + 1];
        strcpy(buffer, str);
    }
  
    // 移動指派運算符
    MyClass& operator=(MyClass&& other) noexcept {
        if (this == &other) {
            return *this;
        }
        if (buffer) {
            delete[] buffer;
        }
        buffer = other.buffer;
        other.buffer = nullptr;
        return *this;
    }
    // 析構函數
    ~MyClass() {
        delete[] buffer;
    }
};

MyClass obj1("abcdefg");
MyClass obj2("xyz");
obj2 = std::move(obj1); // 調用移動指派運算符           

以上代碼中,我們定義了一個 `MyClass` 類,其中包括自定義構造函數、移動指派運算符和析構函數。在建立對象 `obj1` 和 `obj2` 時,會調用自定義構造函數為對象配置設定記憶體并初始化資料。接着,我們将 `obj1` 移動指派給 `obj2`,會調用預設生成的移動指派運算符,将對象的資源進行轉移。最後,我們在程式結束時會自動調用析構函數釋放對象占用的記憶體。

需要注意的是,如果使用者顯式定義了以上任何一個函數,編譯器就不會再為其自動生成預設實作。此外,如果使用者在類中聲明了任何一個構造函數,編譯器也不會再為其生成預設構造函數。