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

C++零大小动态数组与私有构造类的概念判定:编译器分歧谁正确?

C++零大小数组动态分配的标准符合性判定

我定义了一个C++概念heap_constructible,用于检查对象数组是否可动态分配:

template< class T, int N >
concept heap_constructible = requires() {
    delete[] new T[N];
};

意外发现,当数组大小N=0且类的构造函数不可访问(例如private修饰)时,不同编译器的判定结果存在分歧:

class A {
    A();
};

static_assert( !heap_constructible<A, 5> ); // 所有编译器均通过
static_assert( heap_constructible<A, 0> );  // 仅GCC通过

各编译器表现:

  • GCC允许对A类对象进行零大小分配,断言通过
  • Clang报错:calling a private constructor of class 'A',断言失败
  • MSVC判定该概念不满足,断言失败

对概念稍作修改,新增空大括号列表初始化后:

template< class T, int N >
concept heap_constructible1 = requires() {
    delete[] new T[N]{}; // 新增空大括号列表
};

此时的断言结果:

static_assert( heap_constructible1<A, 0> ); // GCC和Clang均通过,MSVC仍判定为false

标准符合性分析

根据C++标准的相关规则:

  1. new T[0]的合法性:当分配零大小数组时,不会创建任何对象,因此也不会调用T的构造函数。这意味着该操作的合法性仅要求T是完整类型,与T的构造函数可访问性无关。

    • GCC的行为符合这一规则:它正确判断零大小分配不需要访问构造函数,因此heap_constructible<A,0>的断言通过。
    • Clang最初的错误在于错误地检查了构造函数的可访问性,不符合标准要求。
  2. new T[0]{}的合法性:带空大括号的值初始化同样不会创建任何对象,因此也不需要访问T的构造函数。Clang在这里修正了判断,使得heap_constructible1<A,0>的断言通过,这一行为符合标准。

  3. MSVC的行为:无论是否使用大括号初始化,MSVC都判定概念不满足,这不符合标准——零大小数组分配不需要依赖构造函数的可访问性。

总结:

  • GCC的两种判定均符合C++标准
  • Clang仅对修改后的heap_constructible1<A,0>判定符合标准,原始概念的判定不符合
  • MSVC的两种判定均不符合标准

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:20:28