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

类类型value-initialization的标准条款解读与代码行为疑问

C++值初始化(value-initialization)的两个常见疑问解析

一、为什么示例代码输出0而非不确定值?

你对标准中“no default constructor”的理解有误。这里的“无默认构造函数”并非指用户未显式声明默认构造函数,而是指编译器无法隐式生成,且用户也未提供可访问的默认构造函数的情况。

你的示例代码里:

class S
{
    long double d;
    friend void f(const S&);
};

编译器会为S隐式生成一个平凡的默认构造函数(因为类没有用户声明的构造函数,也没有阻止隐式生成的因素,比如引用成员、未初始化的const成员等)。此时S属于标准条款(8.1.2)的范畴:类有隐式生成的、非用户提供的默认构造函数,因此值初始化会先执行零初始化,再检查默认初始化的约束——由于这个默认构造函数是平凡的,零初始化后就完成了初始化,所以成员d的值是0,最终输出0。

如果想让S符合(8.1.1)中“无默认构造函数”的情况,你可以给类添加一个用户声明的非默认构造函数,比如:

class S
{
    long double d;
    friend void f(const S&);
public:
    S(int) {} // 用户声明的非默认构造函数,编译器不再隐式生成默认构造函数
};

此时S没有任何默认构造函数,尝试S s{};会直接编译报错,因为默认初始化无法进行。

二、关于[dcl.init]/8.1.1条款的困惑澄清

你误解了条款中“no default constructor”的定义,同时需要明确:当类类型T确实没有可访问的默认构造函数,或者默认构造函数被删除时,T object{};是无法通过编译的,不存在这种情况下还能完成值初始化的合法场景。

条款(8.1.1)的实际含义是:当类T满足以下任一条件时,值初始化的行为等价于默认初始化:

  • T不存在任何可访问的默认构造函数(包括用户未提供、编译器也无法隐式生成的情况);
  • T有用户提供的默认构造函数;
  • T的默认构造函数被删除。

但注意,第一种情况(无默认构造函数)下,默认初始化本身就是非法的,所以T object{};会编译失败——条款只是定义了如果这种初始化合法时的行为,但实际上这种场景下初始化根本无法进行。

比如,当类有一个被删除的默认构造函数时:

class S
{
public:
    S() = delete;
};

尝试S s{};会编译报错,因为默认构造函数被删除,无法完成默认初始化,自然也无法完成值初始化。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:01:23