**拷貝初始化** 語法形式:`Type obj = value;` (使用 `=` 號)。
規定:**等號右側只能是一個單一表達式**,不能像直接初始化 `Type obj(arg1, arg2...)` 那樣提供多個參數。
class Widget {
public:
Widget(int a, int b) { /* ... */ } // 兩個參數構造函數
Widget(const Widget& other) { /* ... */ } // 拷貝構造
};
int main() {
// 1. 直接初始化 - 可提供多個參數匹配構造函數
Widget w1(10, 20); // ✅ 調用 Widget(int, int)
Widget w2{w1}; // ✅ 列表初始化 (C++11) 調用拷貝構造
// 2. 拷貝初始化 - 等號右側只能有一個表達式
Widget w3 = w1; // ✅ 單一表達式 w1,調用拷貝構造
Widget w4 = Widget(10,20); // ✅ 單一表達式: 臨時對象 Widget(10,20),調用移動/拷貝構造 (C++17 強制省略)
// Widget w5 = 10, 20; // ❌ 編譯錯誤:拷貝初始化不允許逗號分隔的多個表達式
// Widget w6 = (10, 20); // ❌ 逗號表達式結果是 20,調用 Widget(int) (若存在) 或報錯
}
| 特性 | 直接初始化 `T obj(args...)` | 拷貝初始化 `T obj = expr` |
|---|---|---|
| 參數數量 | 任意 (匹配構造函數) | **單一表達式** |
| explicit 構造函數 | ✅ 可調用 | ❌ 禁止隱式調用 |
| 臨時對象拷貝 | 可能省略 (NRVO) | C++17 強制省略 (強制拷貝消除) |
| 列表初始化 `{...}` | `T obj{args}` (直接列表初始化) | `T obj = {args}` (拷貝列表初始化) |
Widget w1{10, 20}; // 直接列表初始化,調用 Widget(int, int)
Widget w2 = {10, 20}; // 拷貝列表初始化,等號右側是「單一」初始化列表 {10, 20} ✅
Widget w3 = {w1}; // 拷貝列表初始化,單一元素列表
// 列表初始化禁止隱式縮窄轉換 (如 double->int),更安全
「當我們使用拷貝初始化形式 (即使用 `=`) 時,我們只能提供一個初始值。」
意指:`=` 右側只能有一個表達式 (或一個初始化列表),不能像直接初始化那樣寫多個參數。
「只能提供一個初始值」= **拷貝初始化語法要求等號右側為單一表達式**。這是語法規定,而非語義限制 (單一表達式可以是臨時對象構造表達式 `Widget(1,2)`,實現多參數效果)。現代 C++ 推薦統一使用 **列表初始化 `{...}`**,既安全又統一了直接/拷貝語法差異。