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

值初始化是否调用隐式默认构造函数?C++初始化规则疑问

关于C++空大括号初始化与删除默认构造函数的疑问

问题背景

根据微软文档说明:

若默认构造函数被显式声明且标记为deleted,则无法使用空大括号初始化。

文档给出的报错示例:

#include <string>
using namespace std;

class class_f {
public:
    class_f() = delete;
    class_f(string x): m_string { x } {} // 若删除此构造函数则无错误
    string m_string;
};

int main()
{
    class_f cf{ "hello" };
    class_f cf1{}; // 编译器错误C2280:尝试引用已删除的函数
}

但实际测试发现一个矛盾场景:当类中没有用户提供的构造函数时,即使显式删除了默认构造函数,空大括号初始化仍能正常运行。比如以下代码无编译错误:

#include <string>

class class_f {
public:
    class_f() = delete;
    std::string m_string;
};
int main()
{
    class_f cf1{}; // 此处为何不会触发已删除函数的调用错误?
}

问题解答

核心差异在于类是否属于聚合类型,这直接决定了空大括号初始化的行为逻辑:

1. 第一个示例报错的原因

当类中存在用户自定义的构造函数(比如class_f(string x))时,该类不再是聚合类型。此时class_f cf1{}属于值初始化,编译器会尝试调用类的默认构造函数,但你已经显式删除了这个函数,因此触发C2280错误。

2. 第二个示例正常运行的原因

第二个类中没有用户提供的构造函数(注意:class_f() = delete属于显式删除声明,不算用户提供的自定义构造函数),因此它是聚合类型。对于聚合类型,空大括号初始化走的是聚合初始化逻辑:

  • 聚合初始化会逐个初始化类的成员变量,这里会对m_string执行值初始化(即调用std::string的默认构造函数);
  • 整个过程完全不会尝试调用被删除的class_f默认构造函数,因此不会触发错误。

补充:C++标准规定,仅当类包含用户提供的构造函数时,才会失去聚合类型的属性。显式删除默认构造函数的操作,不会改变类的聚合类型属性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:35:18