gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 15:25:34 25 4
gpt4 key购买 nike

#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;
}

此代码 ( 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 并且没有括号(案例 1)。

C++ 标准是否允许将 new-expression 与第二个语法路径后的零长度数组一起使用,即 type-id 和括号(案例 2)?

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

When the allocated object is an array (that is, the direct-new-declarator syntax is used or the new-type-id or type-id denotes an array type), the new-expression yields a pointer to the initial element (if any) of the array.

(如果有的话) 的措辞将允许一个没有元素的数组,但是,它似乎并不清楚它是指两种情况还是仅指具有 new-type- id 并且没有括号(案例 1)。

提前致谢。

注意事项:

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

    If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

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

    The expression in a direct-new-declarator shall have integral or enumeration type (3.9.1) with a non-negative value.

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

    When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

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

    new-expression:

    ::opt new new-placementopt 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 的 post关于零长度数组。
  7. 示例中的代码是对 SolidSands' 中的测试稍作修改 super 测试套件。

最佳答案

有了括号,您就有了一个常规的 type-id,而不是支持动态数组大小的称为 new-type-id 的特殊语法。

从 C++17 开始,标准没有对 type-id 的这种使用做出特殊规定,因此问题归结为您是否可以编写

auto main() -> int
{
using Argh = int[0];
}

你不能,因为 type-id 的类型是根据虚构的“省略实体名称的变量或函数声明”定义的(C++17 §11.1/1),对于数组变量的声明,规则是“如果常量表达式 (8.20) 存在,则它应是 std::size_t 类型的转换常量表达式> 并且其值应大于零”(C++17 §11.3.4/1)。


现在对此有相当多的解释。例如。如果没有这样合理的解释,最后的引用就不会合理地说数组大小必须是非负的并且可以表示为 size_t。相反,如果没有合理的解释,它会从字面上说这样的声明

int x[42];

无效(当然不是),必须表示为

int x[std::size_t(42)];

过去很容易确定什么是合理的解释或不合理的解释。有人可能会问,这有意义吗?因此,对于上述情况,答案是否定的,并且可以放弃这种可能性。

然而,在某种程度上,C++14 和 C++17 越来越多,我发现早期的可靠技术失败了。但是,由于手头的问题是关于 C++03 功能的,我认为您可以相信这个答案。但如果它是关于 C++14 或更高版本的问题,那么请记住,任何明显明确的答案都可能涉及一些主观解释,这些解释可能无法通过询问是否有意义来解决。

关于c++ - C++ 中的动态零长度数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50105938/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com