在 C++ 中使用複製建構函式
Jinku Hu
2023年10月12日
本文解釋瞭如何在 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