gpt4 book ai didi

c++ - 为什么可变长度数组不是 C++ 标准的一部分?

转载 作者:行者123 更新时间:2023-11-30 16:18:30 25 4
gpt4 key购买 nike

过去几年我不太用C语言。当我读到this question时今天我遇到了一些我不熟悉的C语法。

显然在 C99以下语法有效:

void foo(int n) {
int values[n]; //Declare a variable length array
}

这似乎是一个非常有用的功能。是否曾经讨论过将其添加到 C++ 标准中?如果是,为什么省略它?

一些潜在的原因:

  • 编译器供应商实现起来很困难
  • 与标准的某些其他部分不兼容
  • 可以使用其他 C++ 结构来模拟功能

C++ 标准规定数组大小必须是常量表达式 (8.3.4.1)。

是的,我当然意识到在玩具示例中可以使用 std::vector<int> values(m); ,但这会从堆而不是堆栈分配内存。如果我想要一个多维数组,例如:

void foo(int x, int y, int z) {
int values[x][y][z]; // Declare a variable length array
}

vector版本变得相当笨拙:

void foo(int x, int y, int z) {
vector< vector< vector<int> > > values( /* Really painful expression here. */);
}

切片、行和列也可能分布在整个内存中。

查看 comp.std.c++ 的讨论显然,这个问题颇具争议,争论双方都有一些重量级人物。 std::vector 肯定不明显始终是更好的解决方案。

最佳答案

(背景:我有一些实现 C 和 C++ 编译器的经验。)

C99 中的可变长度数组基本上是一个失误。为了支持 VLA,C99 必须对常识做出以下让步:

  • sizeof x不再总是编译时常量;编译器有时必须生成代码来评估 sizeof -运行时表达式。

  • 允许二维 VLA ( int A[x][y] ) 需要一种新语法来声明采用 2D VLA 作为参数的函数: void foo(int n, int A[][*]) .

  • 在 C++ 世界中不太重要,但对于 C 的嵌入式系统程序员的目标受众来说却极其重要,声明 VLA 意味着占用堆栈的任意大 block 。这是保证的堆栈溢出和崩溃。 (任何时候你声明 int A[n] ,你就隐含地断言你有 2GB 的堆栈空间。毕竟,如果你知道“n 这里肯定小于 1000”,那么你只需声明 int A[1000]n 的 32 位整数 1000 表明您不知道程序的行为应该是什么。)

好的,现在让我们开始讨论 C++。在 C++ 中,我们在“类型系统”和“值系统”之间有与 C89 相同的强烈区别……但我们确实开始以 C 所没有的方式依赖它。例如:

template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s; // equivalently, S<int[n]> s;

如果n不是编译时常量(即,如果 A 是可变修改类型),那么 S 的类型到底是什么? ?会S的类型仅在运行时确定?

这个怎么样:

template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);

编译器必须为 myfunc 的某些实例化生成代码。该代码应该是什么样的?如果我们不知道 A1 的类型,我们如何静态生成该代码?在编译时?

更糟糕的是,如果在运行时发现 n1 != n2 怎么办? ,这样!std::is_same<decltype(A1), decltype(A2)>() ?在这种情况下,请调用myfunc 甚至不应该编译,因为模板类型推导应该失败!我们如何才能在运行时模拟这种行为?

基本上,C++ 正朝着将越来越多的决策插入编译时的方向发展:模板代码生成,constexpr功能评价等。与此同时,C99 正忙于将传统的编译时决策(例如 sizeof )推送到运行时。考虑到这一点,花费精力尝试将 C99 样式的 VLA 集成到 C++ 中真的有意义吗?

正如其他回答者已经指出的那样,当您确实想传达“我不知道我有多少 RAM”的想法时,C++ 提供了许多堆分配机制(std::unique_ptr<int[]> A = new int[n];std::vector<int> A(n); 是显而易见的机制)可能需要。” C++ 提供了一个漂亮的异常处理模型,用于处理不可避免的情况,即您需要的 RAM 量大于您拥有的 RAM 量。但希望这个答案能让您很好地了解为什么 C99 样式的 VLA非常适合 C++,甚至不太适合 C99。 ;)

<小时/>

有关该主题的更多信息,请参阅 N3810 "Alternatives for Array Extensions" ,Bjarne Stroustrup 2013 年 10 月关于 VLA 的论文。 Bjarne 的视角与我的非常不同; N3810 更侧重于为事物寻找良好的 C++ 语法,并阻止在 C++ 中使用原始数组,而我更侧重于元编程和类型系统的含义。我不知道他是否认为元编程/类型系统的影响已经解决、可以解决,或者只是无趣。

<小时/>

"Legitimate Use of Variable Length Arrays" 是一篇很好的博客文章,其中包含许多相同的观点。 (克里斯·韦伦斯,2019-10-27)。

关于c++ - 为什么可变长度数组不是 C++ 标准的一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55884995/

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