C++ 默認構造函數、拷貝構造函數和移動構造函數的區別
構造函數三大類型,默認構造函數、拷貝構造函數和移動構造函數。
1.默認構造函數 (Default Constructor)
默認構造函數是沒有任何參數的構造函數,或者所有參數都有默認值的構造函數。當我們創建一個對象時,若沒有提供初始化參數,程序會調用默認構造函數進行初始化。
特點:
默認構造函數不需要參數,或者所有參數都有默認值。
如果沒有顯式定義,編譯器會自動生成一個默認構造函數(如果沒有其他構造函數的話)。
它用于初始化對象的成員變量,并確保對象處于有效狀態。
示例:
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() { // 默認構造函數
cout << "Default constructor called!" << endl;
}
};
int main() {
MyClass obj; // 創建對象時調用默認構造函數
return 0;
}
輸出:
Default constructor called!
在這個示例中,我們定義了一個名為 MyClass 的類,并實現了一個默認構造函數。當我們創建 obj 對象時,程序自動調用了默認構造函數。
2. 拷貝構造函數 (Copy Constructor)
拷貝構造函數用于通過現有對象來創建一個新的對象。它通常用于對象的復制操作,例如將一個對象傳遞給函數、或者返回一個對象時。
特點:
拷貝構造函數接受一個類的常量引用作為參數。
它的作用是通過另一個對象的內容來初始化新對象。
當對象被復制時,編譯器自動調用拷貝構造函數。
示例:
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() { // 默認構造函數
cout << "Default constructor called!" << endl;
}
MyClass(const MyClass& other) { // 拷貝構造函數
cout << "Copy constructor called!" << endl;
}
};
int main() {
MyClass obj1; // 調用默認構造函數
MyClass obj2 = obj1; // 調用拷貝構造函數
return 0;
}
輸出:
Default constructor called!
Copy constructor called!
在這個示例中,我們創建了一個對象 obj1,并將其傳遞給 obj2,這時會調用拷貝構造函數來創建一個新的對象 obj2,并復制 obj1 的內容。
3. 移動構造函數 (Move Constructor)
移動構造函數用于通過轉移資源來構造對象,避免不必要的資源復制。在某些情況下,當我們傳遞臨時對象或者即將銷毀的對象時,移動構造函數會“竊取”對象的資源,而不是進行復制操作。這種方式大大提高了程序的性能,尤其是在處理大對象或動態內存分配時。
特點:
移動構造函數接受一個右值引用作為參數。
它會將資源從一個對象轉移到另一個對象,而不是復制資源。
移動構造函數通常用于處理臨時對象或返回對象。
示例:
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() { // 默認構造函數
cout << "Default constructor called!" << endl;
}
MyClass(MyClass&& other) { // 移動構造函數
cout << "Move constructor called!" << endl;
}
};
MyClass createObject() {
MyClass temp;
return temp; // 移動構造函數被調用
}
int main() {
MyClass obj = createObject(); // 使用移動構造函數
return 0;
}
輸出:
Default constructor called!
Move constructor called!
在這個示例中,createObject 函數返回一個 MyClass 對象。當 temp 返回時,程序會調用移動構造函數,因為 temp 是一個臨時對象。通過移動構造函數,obj 將直接接管 temp 的資源,而無需復制資源。
4. 總結
默認構造函數、拷貝構造函數和移動構造函數各自有不同的用途:
默認構造函數:當我們創建一個對象時,它會被調用,進行默認初始化。
拷貝構造函數:在需要復制對象時被調用,如對象傳遞、返回值傳遞等。
移動構造函數:當傳遞或返回臨時對象時使用,它通過“竊取”資源避免了復制,提升了性能。