預設建構函式
預設建構函式是一種無需任何引數即可呼叫的建構函式。
目錄 |
[編輯] 語法
類別名稱 (參數列表 (可選)); |
(1) | ||||||||
類別名稱 (參數列表 (可選)) 函式主體 |
(2) | ||||||||
類別名稱 () = default; |
(3) | (C++11 起) | |||||||
類別名稱 (參數列表 (可選)) = delete; |
(4) | (C++11 起) | |||||||
類別名稱 ::類別名稱 (參數列表 (可選)) 函式主體 |
(5) | ||||||||
類別名稱 ::類別名稱 () = default; |
(6) | (C++11 起) | |||||||
| class-name | - | 正在宣告預設建構函式的類別 |
| 參數列表 | - | 一個參數列表,其中所有參數(除了參數包)(C++11 起)都具有預設引數 |
| function-body | - | 預設建構函式的函式主體 |
[編輯] 解釋
[編輯] 隱式宣告的預設建構函式
如果類別型別沒有使用者宣告的建構函式或建構函式模板,編譯器將會隱式宣告一個預設建構函式,作為其類別的inline public成員。
隱式宣告的(或在其首次宣告時預設化的)預設建構函式具有一個異常規範,如動態異常規範(C++17 前) noexcept 規範(C++17 起)所述。
[編輯] 隱式定義的預設建構函式
如果建構函式是隱式宣告的(C++11 前)隱式宣告的或明確預設化的預設建構函式沒有定義為已刪除(C++11 起),則當其被odr-use或常數求值所需(C++11 起)時,它將由編譯器隱式定義。
|
如果類聯集類別 (union-like class) |
(C++26 起) |
一個(C++26 前)否則,一個(C++26 起)隱式定義的預設建構函式與一個擁有空主體和空初始化列表的使用者定義建構函式具有相同的效果。也就是說,它會呼叫基底類別以及此類別的非靜態成員的預設建構函式。擁有空使用者提供建構函式的類別型別在值初始化期間,其處理方式可能與擁有隱式定義預設建構函式的類別型別不同。
|
如果這滿足constexpr 建構函式(C++23 前)constexpr 函式(C++23 起)的要求,則生成的建構函式是 constexpr。 如果存在一些使用者定義的建構函式,使用者仍然可以使用關鍵字 default 來強制編譯器自動生成一個預設建構函式,該建構函式在其他情況下會是隱式宣告的。 |
(C++11 起) |
已刪除的預設建構函式如果滿足以下任一條件,則類別
如果沒有使用者定義的建構函式且隱式宣告的預設建構函式不是平凡的,使用者仍然可以使用關鍵字 delete 來抑制編譯器自動生成隱式定義的預設建構函式。 |
(C++11 起) |
[編輯] 平凡的預設建構函式
如果滿足以下所有條件,則類別 T 的預設建構函式是平凡的
- 該建構函式是隱式宣告的(C++11 前)非使用者提供的(C++11 起)。
-
T沒有虛擬成員函式。 -
T沒有虛擬基底類別。
|
(C++11 起) |
T的每個直接基底類別都有一個平凡的預設建構函式。
|
(直到 C++26) |
|
(C++26 起) |
平凡的預設建構函式是不執行任何動作的建構函式。所有與 C 語言相容的資料型別(POD 型別)都可以平凡地預設建構。
[編輯] 合資格的預設建構函式
|
如果預設建構函式是使用者宣告的,或者既是隱式宣告的又是可定義的,那麼它就是合資格的。 |
(直到 C++11) |
|
如果預設建構函式未被刪除,那麼它就是合資格的。 |
(C++11 起) (直到 C++20) |
|
如果滿足以下所有條件,則預設建構函式是合資格的
|
(自 C++20 起) |
合資格預設建構函式的平凡性決定了類別是否為隱式生命週期型別,以及類別是否為平凡可複製型別。
[編輯] 附註
| 特性測試巨集 | 數值 | 標準 | 功能 |
|---|---|---|---|
__cpp_trivial_union |
202502L |
(C++26) | 放鬆聯集的特殊成員函式的平凡性要求 |
[編輯] 範例
struct A { int x; A(int x = 1): x(x) {} // user-defined default constructor }; struct B : A { // B::B() is implicitly-defined, calls A::A() }; struct C { A a; // C::C() is implicitly-defined, calls A::A() }; struct D : A { D(int y) : A(y) {} // D::D() is not declared because another constructor exists }; struct E : A { E(int y) : A(y) {} E() = default; // explicitly defaulted, calls A::A() }; struct F { int& ref; // reference member const int c; // const member // F::F() is implicitly defined as deleted }; // user declared copy constructor (either user-provided, deleted or defaulted) // prevents the implicit generation of a default constructor struct G { G(const G&) {} // G::G() is implicitly defined as deleted }; struct H { H(const H&) = delete; // H::H() is implicitly defined as deleted }; struct I { I(const I&) = default; // I::I() is implicitly defined as deleted }; int main() { A a; B b; C c; // D d; // compile error E e; // F f; // compile error // G g; // compile error // H h; // compile error // I i; // compile error }
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。
| DR | 應用於 | 出版時的行為 | 正確的行為 |
|---|---|---|---|
| CWG 1353 | C++11 | 隱式宣告的預設建構函式被 定義為已刪除的條件未考慮多維陣列型別 |
考量這些型別 |
| CWG 2084 | C++11 | 預設成員初始化器對於是否 聯集的預設化的預設建構函式會被刪除沒有影響 |
它們阻止了預設化的預設 建構函式被刪除 |
| CWG 2595 | C++20 | 如果存在,則預設建構函式不合資格 另一個更受約束的預設建構函式 但如果該移動建構函式未滿足其相關限制 |
在此情況下它可以是合格的 |
| CWG 2871 | C++98 | 預設建構函式將會被隱式宣告 即使存在使用者宣告的建構函式模板 |
沒有隱式宣告 在此情況下 |