代碼語境
class A {
Member me; // 假設 Member 有構造函數 Member(int)
void func() {
me = 1; // 情況 1
me(1); // 情況 2(僅在特定語境合法)
}
};
情況 1:me = 1 (賦值表達式)
- 若
me 已初始化(構造函數體中):調用 Member::operator=(int) 或 operator=(const Member&)(經隱式轉換構造臨時對象)。
- 若在成員初始化列表中:
A() : me(1) {} 為直接初始化,調用 Member(int) 構造函數,**不會**調用賦值運算符。
- 若
Member 無 operator=(int) 但有 Member(int):編譯器構造臨時 Member(1) 再調用 operator=(const Member&)(拷貝/移動賦值)。
情況 2:me(1) (函數調用語法)
- 在成員初始化列表中:
A() : me(1) {} 直接調用 Member(int) 構造函數(同情況 1 列表初始化)。
- 在函數體中:
me(1) 嘗試調用 Member::operator()(int)(函數調用運算符)。若 Member 未定義 operator(),**編譯錯誤**。
- C++11 統一初始化:
me{1} 可用於列表初始化與賦值(me = {1}),語義更一致。
核心差異總結表
| 語境 | me = 1 | me(1) |
| 構造函數初始化列表 | 錯誤語法(非 C++11 聚合初始化) | ✓ 直接初始化,調用構造函數 |
| 構造函數體 / 普通函數 | 賦值操作,調用 operator= | 調用 operator(),若無則編譯錯誤 |
| 臨時對象生成 | 可能隱式生成 | 不生成(除非 operator() 內部創建) |
最佳實踐
- 初始化列表統一使用
me(1) 或 me{1}。
- 賦值場景明確寫
me = 1,若需避免臨時對象,為 Member 提供 operator=(int)。
- 避免在函數體使用
me(1),除非 Member 設計為可調用對象(Functor)。