類別包含指標成員時,預設複製構造函數與賦值運算符執行「淺拷貝」(僅複製指標值),導致多物件共用同一塊堆記憶體,析構時雙重釋放或存取已釋放記憶體。
class C {
public:
C(int v) { ptr = new int(v); val = v; }
~C() { delete ptr; }
void Del() { val=0; delete ptr; }
int *ptr; int val;
};
int main() {
C c1(2), c2(3);
c2 = c1; // 淺拷貝:c2.ptr 指向 c1.ptr 同一記憶體
c1.Del(); // 釋放記憶體
// c2.ptr 成懸空指標,後續存取 UB
}
C(const C& other) 深拷貝指標指向的資料。C& operator=(const C& other) 釋放舊資源、深拷貝新資源、自我賦值檢查。
class C {
public:
C(int v) : ptr(new int(v)), val(v) {}
~C() { delete ptr; }
// 複製構造函數
C(const C& other) : ptr(new int(*other.ptr)), val(other.val) {}
// 賦值運算符
C& operator=(const C& other) {
if (this != &other) { // 自我賦值檢查
delete ptr; // 釋放舊資源
ptr = new int(*other.ptr); // 深拷貝
val = other.val;
}
return *this;
}
void Del() { val=0; delete ptr; ptr=nullptr; }
int *ptr; int val;
};
operator=(避免對未初始化 ptr 刪除)。*this。std::unique_ptr 或 std::shared_ptr 自動管理資源,避免手寫三大法則。
int main() {
C c1(2), c2(3);
c2 = c1; // 深拷貝
c1.Del(); // 僅影響 c1
printf("c2.ptr=%p val=%d\n", c2.ptr, *c2.ptr); // 正常輸出 2
return 0;
}
管理動態資源的類別必須遵循「三大法則」(C++11 後為「五大法則」含移動語意)。深拷貝確保物件語意獨立,避免資源管理錯誤。現代 C++ 應優先使用智慧指標與標準容器,讓編譯器自動生成正確的特殊成員函數。