ClassName(const ClassName& other); // 唯一參數為 const 參考
ClassName b = a;、func(a)(值傳遞)、return a(值傳回)。若類別含指標成員指向動態記憶體,預設複製僅複製指標值,導致兩物件共用同一記憶體區塊:
class Bad {
int* data;
public:
Bad(int n) { data = new int[n]; }
~Bad() { delete[] data; } // 雙重釋放崩潰!
};
int main() {
Bad a(10);
Bad b = a; // 淺層複製:a.data == b.data
} // a、b 解構時雙重 delete 同一記憶體
在複製建構函式中重新配置記憶體並複製內容:
class Good {
int* data;
size_t len;
public:
Good(int n) : len(n) { data = new int[n]; }
Good(const Good& other) : len(other.len) { // 深層複製
data = new int[len];
std::copy(other.data, other.data + len, data);
}
Good& operator=(const Good& other) { // 指派運算子同理
if (this != &other) {
delete[] data;
len = other.len;
data = new int[len];
std::copy(other.data, other.data + len, data);
}
return *this;
}
~Good() { delete[] data; }
};
#include
#include
using namespace std;
class CA {
int a;
char* str;
public:
CA(int b, const char* cstr) : a(b) {
str = new char[b];
strcpy(str, cstr);
}
CA(const CA& c) : a(c.a) { // 深層複製
str = new char[a];
if (str) strcpy(str, c.str);
}
void Show() { cout << str << endl; }
~CA() { delete[] str; }
};
int main() {
CA A(10, "Hello!");
CA B = A; // 呼叫複製建構函式
B.Show(); // 輸出 Hello!
return 0;
}
std::string、std::vector、std::unique_ptr、std::shared_ptr 等 RAII 類別,讓編譯器自動合成正確的特殊成員函式,完全避免手動管理記憶體。= delete 禁用複製:CA(const CA&) = delete; CA& operator=(const CA&) = delete;| 場景 | 預設行為 | 需自訂時 |
|---|---|---|
| 無指標/資源成員 | 正確(位元複製即語意複製) | 罕見 |
| 含指標/動態資源 | 淺層複製 → 雙重釋放/資料競爭 | 必須實作深層複製或禁用 |
| 含參考/const 成員 | 編譯錯誤(預設複製無法處理) | 必須自訂 |