預設建構函式
預設建構函式是無需任何實參即可呼叫的建構函式。
目錄 |
[編輯] 語法
類名 ( 引數列表 (可選)); |
(1) | ||||||||
類名 ( 引數列表 (可選)) 函式體 |
(2) | ||||||||
類名 () = default; |
(3) | (C++11 起) | |||||||
類名 ( 引數列表 (可選)) = delete; |
(4) | (C++11 起) | |||||||
類名 :: 類名 ( 引數列表 (可選)) 函式體 |
(5) | ||||||||
類名 :: 類名 () = default; |
(6) | (C++11 起) | |||||||
類名 | - | 宣告預設建構函式的類 |
引數列表 | - | 一個引數列表,其中所有引數(引數包除外)(C++11 起)都有預設實參 |
函式體 | - | 預設建構函式的函式體 |
[編輯] 解釋
[編輯] 隱式宣告的預設建構函式
如果類型別沒有使用者宣告的建構函式或建構函式模板,編譯器將隱式宣告一個預設建構函式作為其類的inline public成員。
隱式宣告的(或在其首次宣告時被預設化的)預設建構函式具有異常規範,如動態異常規範(C++17 前) noexcept 規範(C++17 起)中所述。
[編輯] 隱式定義的預設建構函式
如果建構函式是隱式宣告的(C++11 前)隱式宣告或顯式預設化的預設建構函式未被定義為已刪除(C++11 起),則當其被odr-使用或常量求值所需(C++11 起)時,編譯器會隱式定義它。
如果類聯合`T`的預設建構函式是平凡的,那麼對於每個聯合`U`,如果`U`是`T`或`T`的匿名聯合成員,如果`U`的第一個變體成員(如果有)具有隱式生命週期型別,則`T`的預設建構函式將開始該成員的生命週期,如果它不是其聯合的活躍成員。 |
(C++26 起) |
一個(C++26 前)否則,一個(C++26 起)隱式定義的預設建構函式具有與帶有空函式體和空初始化列表的使用者定義建構函式相同的效果。也就是說,它呼叫基類和此類的非靜態成員的預設建構函式。帶有空使用者提供建構函式的類型別在值初始化期間可能與帶有隱式定義預設建構函式的類型別被不同對待。
如果這滿足constexpr 建構函式(C++23 前)constexpr 函式(C++23 起)的要求,則生成的建構函式是constexpr。 如果存在一些使用者定義的建構函式,使用者仍然可以透過關鍵字default強制編譯器自動生成原本會隱式宣告的預設建構函式。 |
(C++11 起) |
已刪除的預設建構函式如果滿足以下任何條件,則類`T`的隱式宣告或顯式預設化的預設建構函式被定義為已刪除
如果不存在使用者定義的建構函式,並且隱式宣告的預設建構函式不是平凡的,使用者仍然可以使用關鍵字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++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
CWG 1353 | C++11 | 隱式宣告的預設建構函式在以下情況下被 定義為已刪除,但未考慮多維陣列型別 |
考慮這些型別 |
CWG 2084 | C++11 | 預設成員初始化器對聯合的預設建構函式是否 被刪除沒有影響 |
它們阻止了預設 建構函式被刪除 |
CWG 2595 | C++20 | 如果存在另一個約束更嚴格的預設建構函式,則預設建構函式不合格 另一個約束更嚴格的預設建構函式 則複製建構函式不合格 |
它在這種情況下可以合格 |
CWG 2871 | C++98 | 即使存在使用者宣告的建構函式模板,也會隱式宣告預設建構函式 即使存在使用者宣告的建構函式模板 |
無隱式宣告 在這種情況下 |