移動構造函數(Move Constructor)中為什麼要將來源對象的指標成員置為 nullptr?
移動構造函數的簽名為 ClassName(ClassName&& other),接收**右值引用**參數。其核心目的是**轉移資源所有權**,而非複製資源。典型場景:管理動態記憶體、檔案句柄、Socket、智慧指標等資源的類別。
class Buffer {
char* data_;
size_t size_;
public:
Buffer(Buffer&& other) : data_(other.data_), size_(other.size_) {
other.data_ = nullptr; // 關鍵步驟
other.size_ = 0;
}
~Buffer() { delete[] data_; } // 安全:delete nullptr 無操作
};
Buffer a(1024);
Buffer b = std::move(a); // a.data_ 已置 nullptr
// a 析構時 delete[] nullptr 安全
// b 析構時 delete[] 真實記憶體正確
若不置空,a 與 b 同時持有相同指標,析構時雙重 delete 導致未定義行為(崩潰/堆損壞)。
C++ 標準規定:被移動後的對象處於「有效但未指定狀態」。置空指標是建立此狀態的標準做法,使對象:
a = Buffer(2048))std::vector 擴容時移動元素,若移動拋出異常需回滾。置空保證來源對象析構不拋異常,滿足 noexcept 要求,讓容器選擇移動而非複製,提升效能。
| 特性 | 複製構造 | 移動構造 |
|---|---|---|
| 參數類型 | const T& | T&& |
| 資源處理 | 深度複製(新建記憶體、複製數據) | 轉移所有權(指標賦值、置空來源) |
| 時間複雜度 | O(n) | O(1) |
| 來源對象狀態 | 不變 | 有效但未指定(通常置空) |
std::unique_ptr、std::vector、std::string 等已實現移動語義的標準類別,**手寫移動構造極少見**= default/= deletenoexcept:Buffer(Buffer&& other) noexcept,啟用容器優化總結:置空指標是移動語義「轉移所有權、避免雙重釋放、建立有效狀態」的核心機制,是 C++ 資源管理安全性的基石。