gpt4 book ai didi

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

转载 作者:bug小助手 更新时间:2023-10-28 01:31:58 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]) 需要一种新语法来声明将二维 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++ 提供了一个漂亮的异常处理模型来处理不可避免的情况,即您需要的 RAM 量大于您拥有的 RAM 量。但希望 这个 答案能让您很好地了解为什么 C99 风格的 VLA 适合 C++,甚至不适合 C99。 ;)


有关该主题的更多信息,请参阅 N3810 "Alternatives for Array Extensions" , Bjarne Stroustrup 2013 年 10 月关于 VLA 的论文。 Bjarne 的 POV 和我的很不一样; N3810 更侧重于为事物找到一个好的 C++ 类似的语法,并且不鼓励在 C++ 中使用原始数组,而我更关注元编程和类型系统的含义。我不知道他是否认为元编程/类型系统的影响已解决、可解决或仅仅是无趣。


一篇很好的博文是 "Legitimate Use of Variable Length Arrays" (克里斯·韦隆斯,2019-10-27)。

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

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