在 C++ 中使用複製建構函式

Jinku Hu 2023年1月30日 2021年6月28日
  1. 在 C++ 中使用複製建構函式從另一個相同型別的物件初始化一個物件
  2. 使用複製賦值運算子在 C++ 中定義物件的賦值運算子過載
在 C++ 中使用複製建構函式

本文解釋瞭如何在 C++ 中使用複製建構函式的幾種方法。

在 C++ 中使用複製建構函式從另一個相同型別的物件初始化一個物件

類中有幾個操作統稱為複製控制。這些操作定義瞭如何複製、移動、分配或銷燬給定類型別的物件。在本文中,我們將只關注複製建構函式和複製賦值。

複製建構函式通過複製作為引用傳遞的引數的值來初始化物件(它通常作為 const 引用傳遞)。該類不需要像任何其他複製控制操作一樣定義複製建構函式,因為編譯器會自動為未定義的操作定義合成操作。不過,通常後者可能會導致問題。合成複製建構函式將引數物件的每個成員複製到正在建立的物件。可能有一些其他類型別的成員,它們被它們的複製建構函式複製。相比之下,內建型別物件是直接複製的。

以下示例程式碼演示了 MyClass 的複製建構函式的行為,它採用複製建構函式的唯一必需引數,然後初始化資料成員。另一方面,複製建構函式可以有額外的引數,這些引數必須是可選的並且有預設值。

當第一次建立 MyClass 型別的物件時,會呼叫預設建構函式;但是,如果我們將 m1 分配給新建立的 m3 變數,則會呼叫複製建構函式。後一種操作也稱為複製初始化,它可以使用複製建構函式或移動建構函式(在另一篇文章中討論)。

#include <iostream>

using std::cout; using std::endl;
using std::pair;

class MyClass {
private:
    int n1{};
    int n2{};
public:
    MyClass(int x, int y) : n1(x), n2(y) {
        cout << "Constructor 1 is called" << endl;
    };

    MyClass(const MyClass& src) {
        cout << "Copy Constructor is called " << endl;
        n1 = src.n1;
        n2 = src.n2;
    }

    auto getPair() { return pair<int, int>(n1, n2); }

    ~MyClass() = default;
};


int main() {
    MyClass m1(12, 21);
    cout << "------------------" << endl;
    MyClass m2(11, 33);
    cout << "------------------" << endl;
    MyClass m3 = m1;
    cout << "------------------" << endl;

    cout << m1.getPair().first << m1.getPair().second << endl;
    cout << m2.getPair().first << m2.getPair().second << endl;
    cout << m3.getPair().first << m3.getPair().second << endl;

    return EXIT_SUCCESS;
}

輸出:

Constructor 1 is called
------------------
Constructor 1 is called
------------------
Copy Constructor is called
------------------
1221
1133
1221

使用複製賦值運算子在 C++ 中定義物件的賦值運算子過載

複製賦值運算子定義瞭如何分配相同型別的物件。如果使用者沒有明確定義它,編譯器也會綜合這個操作。複製賦值的描述類似於其他運算子過載函式。它採用與類相同型別的引數,通常返回對左側運算元的引用。複製賦值運算子必須定義為成員函式。

下一個程式碼片段為 MyClass 新增複製賦值運算子,並在將 m2 物件分配給 m1 時呼叫它。

#include <iostream>

using std::cout; using std::endl;
using std::pair;

class MyClass {
private:
    int n1{};
    int n2{};
public:
    MyClass(int x, int y) : n1(x), n2(y) {
        cout << "Constructor 1 is called" << endl;
    };

    MyClass(const MyClass& src) {
        cout << "Copy Constructor is called " << endl;
        n1 = src.n1;
        n2 = src.n2;
    }

    MyClass& operator=(const MyClass& src){
        cout << "Copy Assignment is called " << endl;
        n1 = src.n1;
        n2 = src.n2;
        return *this;
    }

    auto getPair() { return pair<int, int>(n1, n2); }

    ~MyClass() = default;
};


int main() {
    MyClass m1(12, 21);
    cout << "------------------" << endl;
    MyClass m2(11, 33);
    cout << "------------------" << endl;
    MyClass m3 = m1;
    cout << "------------------" << endl;
    m1 = m2;
    cout << "------------------" << endl;

    cout << m1.getPair().first << m1.getPair().second << endl;
    cout << m2.getPair().first << m2.getPair().second << endl;
    cout << m3.getPair().first << m3.getPair().second << endl;

    return EXIT_SUCCESS;
}

輸出:

Constructor 1 is called
------------------
Constructor 1 is called
------------------
Copy Constructor is called
------------------
Copy Assignment is called
------------------
1221
1133
1221
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相關文章 - C++ Constructor