指派運算子(operator=)是 C++ 類別資源管理的核心,正確實作需處理自我指派、資源釋放、異常安全、高效交換。本文透過 Book 類別完整範例,深度解析 Copy-and-Swap 慣用語、std::swap 非擲出交換、強烈異常安全保證、拷貝建構函式與指派運算子關係,提供工程級可複製類別實作範本。
class Book {
char *name;
char *author;
double price;
// 私有交換函式:非擲出、高效
Book& swap(Book& rhs) {
std::swap(name, rhs.name);
std::swap(author, rhs.author);
std::swap(price, rhs.price);
return *this;
}
public:
// 建構函式
Book(const char *n, const char *a, double p) : price(p) {
name = new char[strlen(n) + 1];
author = new char[strlen(a) + 1];
strcpy(name, n);
strcpy(author, a);
}
// 拷貝建構函式
Book(const Book& b) : price(b.price) {
name = new char[strlen(b.name) + 1];
author = new char[strlen(b.author) + 1];
strcpy(name, b.name);
strcpy(author, b.author);
}
// 指派運算子:Copy-and-Swap
Book& operator=(const Book& rhs) {
Book(rhs).swap(*this); // 1. 拷貝建構臨時物件 2. 交換資源 3. 臨時物件析構釋放舊資源
return *this;
}
// 解構函式
~Book() {
delete[] name;
delete[] author;
}
};
Book(rhs) 使用拷貝建構函式,可能拋出異常(記憶體不足),但原物件 *this 未被修改swap(*this) 使用 std::swap 交換指標/值,非擲出保證*this 的舊資源,析構函式釋放| 特性 | 傳統實作 | Copy-and-Swap |
|---|---|---|
| 自我指派 | 需額外 if (this == &rhs) | 自動處理(拷貝自己再交換無害) |
| 異常安全 | 基本保證(可能資源洩漏/狀態損壞) | 強烈保證(失敗不修改 *this) |
| 程式碼重用 | 建構/指派/解構邏輯分散 | 複用拷貝建構+解構 |
| 效能 | 釋放再分配 | 交換指標 O(1) |