C++中的动态零长度数组

Jos*_*uis 11 c++ arrays new-operator dynamic-memory-allocation c++11

#include <stdlib.h>

void *operator new[](size_t size, int n){
    if( size != 0 && n != 0 )
        return calloc(n, size);
    return calloc(1, 1);
}

int main(){

    int * p1;
    const int i = 0;

//  p1 = new (20)  int[i] ; // Case 1 (OK)
    p1 = new (20) (int[i]); // Case 2 (Warning)

    if( p1 == 0 )
        return 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码(https://godbolt.org/g/hjo7Xn)与Clang 6.0.0成功编译,但是,GCC 7.3发出警告说在C++中禁止使用零长度数组.如果删除了括号(案例1),警告就会消失.

与静态分配的零长度数组(C++ 03:8.3.4/1)不同,允许动态分配的零长度数组(C++ 03:5.3.4/6).尽管如此,在C++标准中,只有在遵循new-expression的两个可能语法路径之一时,才明确允许后者,即具有new-type-id且没有括号的路径(Case 1).

是否允许C++标准在第二个语法路径后使用带有零长度数组的new-expression,即使用type-id和括号(Case 2)?

唯一相关的引用是C++ 03:5.3.4/5:

当分配的对象是数组时(即,使用direct-new-declarator语法或new-type-idtype-id表示数组类型),new-expression产生指向初始元素的指针(如果任何)数组.

措辞(if any)将允许没有元素的数组,但是,如果它既引用了两种情况,也不仅仅指具有new-type-id且没有括号的情况,则似乎不清楚(情况1).

提前致谢.

笔记:

  1. ISO/IEC 14882:2003,第8.3.4节,第1段:

    如果存在常量表达式(5.19),则它应为整数常量表达式,其值应大于零.

  2. ISO/IEC 14882:2003,第5.3.4节,第6段:

    表达在一个直接的新声明符应具有与非负值整数或枚举类型(3.9.1).

  3. ISO/IEC 14882:2003,第5.3.4节,第7段:

    当的值表达在一个直接的新声明符为零,分配函数被调用,以没有元素分配一个数组.

  4. ISO/IEC 14882:2003,第5.3.4节,第1段:

    new-expression:

    :: opt new new-placement opt new-type-id new-initializeropt

    :: opt new new-placementopt(type-id)new-initializeropt

  5. 虽然上面的引用来自C++ 03标准,但据我所知,这个问题在较新版本的C++标准(C++ 11,C++ 14和C++ 17)中仍然不清楚.
  6. 有趣的Herb Sutter 关于零长度数组的帖子.
  7. 示例中的代码是SolidSands的 SuperTest套件中稍微修改过的测试.

Dav*_*ing 0

不可以,零大小的情况不能使用带括号的type-id。大小为 0 的数组的行为(在当前草案中)仅针对noptr-new-declarator ( [expr.new]/7 )中的表达式给出。具有括号类型的A尝试创建该类型的对象,并且不存在大小为 0 ( [dcl.array]/1 ) 的数组,甚至不存在类型 ID ( [dcl.name]/1 )。new

零大小的数组当然是常见的扩展,因此实际结果可能会有所不同。