You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

删除默认构造函数后仍保留大括号初始化的C++实现方法

解决方案

C++20及以上版本

利用C++20允许聚合类型包含基类的特性,通过继承一个删除了默认构造函数的空基类,既能禁止意外的默认初始化,又能保留聚合类型的所有初始化能力:

struct NoDefault {
    NoDefault() = delete;
};

struct Foo : NoDefault {
    int a;
    int b;
    const char* c;
};

使用效果:

  • Foo foo;:编译错误,基类默认构造函数已删除,无法完成默认初始化
  • Foo foo1 = {};:正常编译,所有成员被零初始化(数值型为0,指针为空)
  • Foo foo2 = {1, 2, "hello"};:正常编译,按顺序初始化成员
  • Foo foo3 = {.a=10, .b=20, .c="world"};:正常编译,支持C++20指定初始化器语法

原理:Foo属于C++20标准下的聚合类型(无用户声明构造函数、无私有/保护非静态成员、无虚函数/虚基类),因此支持所有聚合初始化方式;继承的NoDefault基类阻断了默认初始化路径,避免了成员未初始化的风险。

C11至C17版本

这些版本不允许聚合类型包含基类,无法完全满足所有初始化需求,可选择以下近似方案:

方案1:构造函数约束

定义对应参数的构造函数并删除默认构造,支持顺序初始化,但无法使用指定初始化器(仅聚合类型支持):

struct Foo {
    int a;
    int b;
    const char* c;

    Foo() = delete; // 禁止默认初始化
    constexpr Foo(int a_, int b_, const char* c_) : a(a_), b(b_), c(c_) {}
    
    // 提供零初始化的替代方式
    constexpr Foo(std::nullptr_t) : a(0), b(0), c(nullptr) {}
};

使用效果:

  • Foo foo;:编译错误
  • Foo foo1 = nullptr;:实现零初始化(替代{}语法)
  • Foo foo2 = {1, 2, "hello"};:正常编译
  • Foo foo3 = {.a=10, ...};:编译错误(非聚合类型不支持指定初始化器)

方案2:编译选项约束

通过编译器警告强制初始化:开启-Wuninitialized(GCC/Clang)或/W4(MSVC)警告,并将警告视为错误(-Werror//WX),从编译层面避免未初始化的情况,但这属于工具链约束而非代码强制。

关键说明
  • 若要同时支持{}、顺序初始化、指定初始化器三种语法,C++20是必需的,只有该版本能在保留聚合初始化能力的同时阻断默认初始化。
  • std::initializer_list仅适合同质元素集合,无法适配不同类型成员的初始化场景,因此不适合本题需求。

内容的提问来源于stack exchange,提问作者Manishearth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:50:06