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

Jinku Hu 2023年10月12日
  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
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook

相關文章 - C++ Constructor