Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不';t可变长度数组是C++;标准_C++_Arrays_Standards_Variable Length Array_Variable Length - Fatal编程技术网

C++ 为什么不';t可变长度数组是C++;标准

C++ 为什么不';t可变长度数组是C++;标准,c++,arrays,standards,variable-length-array,variable-length,C++,Arrays,Standards,Variable Length Array,Variable Length,在过去的几年里,我很少使用C语言。当我今天读的时候,我遇到了一些我不熟悉的C语法 显然,以下语法是有效的: void foo(int n) { int values[n]; //Declare a variable length array } 这似乎是一个非常有用的功能。有没有讨论将它添加到C++标准中,如果是,为什么省略了? 一些潜在原因: 编译器供应商难以实现的问题 与标准的其他部分不兼容 功能可以用其他C++构造仿真 C++标准声明数组大小必须是常数表达式(83.4.1)

在过去的几年里,我很少使用C语言。当我今天读的时候,我遇到了一些我不熟悉的C语法

显然,以下语法是有效的:

void foo(int n) {
    int values[n]; //Declare a variable length array
}
这似乎是一个非常有用的功能。有没有讨论将它添加到C++标准中,如果是,为什么省略了? 一些潜在原因:

  • 编译器供应商难以实现的问题
  • 与标准的其他部分不兼容
  • 功能可以用其他C++构造仿真

C++标准声明数组大小必须是常数表达式(83.4.1)。

是的,我当然意识到在玩具示例中可以使用
std::vector value(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. */);
}
void foo(intx,inty,intz){
vector>值(/*此处的表达式非常痛苦。*/);
}
片、行和列也可能分布在内存中


看看
comp.std.c++
上的讨论,很明显,这个问题很有争议,争论双方都有一些非常重要的名字。显然,std::vector始终是一个更好的解决方案并不明显。

为此使用std::vector。例如:

std::vector<int> values;
values.resize(n);
template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s;  // equivalently, S<int[n]> s;
std::向量值;
值。调整大小(n);

内存将在堆上分配,但这只存在一个小的性能缺陷。此外,在堆栈上不分配大的数据库锁是明智的,因为它的大小相当有限。

数组是这样的,是C99的一部分,但不是标准C++的一部分。正如其他人所说的,向量总是一个更好的解决方案,这可能是为什么可变大小的数组不在C++标准中(或者在建议的C++ 0x标准中)。

BTW,对于“为什么”C++标准是这样的问题,适度的USENET新闻组是要去的地方。

< P>这被认为包含在C++ +1x中(这是对我之前所说的一个更正)。
<> P>这在C++中是不太有用的,因为我们已经有了<代码> STD::Vector 来填充这个角色。

< P>如果你知道编译时的值,你可以做如下:

template <int X>
void foo(void)
{
   int values[X];

}
模板
无效foo(无效)
{
int值[X];
}

编辑:您可以创建一个使用堆栈分配器(alloca)的向量,因为分配器是一个模板参数。

最近在usenet中对此展开了讨论:

我同意那些似乎同意必须在堆栈上创建一个潜在的大数组(通常只有很少的可用空间)的人的观点,这是不好的。理由是,如果事先知道大小,可以使用静态数组。如果您事先不知道大小,您将编写不安全的代码

C99 VLA可以提供一个小的好处,即能够创建小数组,而不会浪费空间或调用未使用元素的构造函数,但它们会对类型系统带来相当大的更改(您需要根据运行时值指定类型——这在当前C++中还不存在,除了<代码>新< /Cord>运算符类型说明符,但它们被专门处理,这样运行时的度不会超出<代码>新< /COD>运算符的范围。< /P>
您可以使用
std::vector
,但它并不完全相同,因为它使用动态内存,让它使用自己的堆栈分配器并不容易(对齐也是一个问题)。它也不能解决同样的问题,因为向量是可调整大小的容器,而VLA是固定大小的。该提案旨在引入基于库的解决方案,作为基于语言的VLA的替代方案。但是,据我所知,它不会成为C++0x的一部分。

您可以始终使用alloca()要在运行时在堆栈上分配内存,请执行以下操作:

void foo (int n)
{
    int *values = (int *)alloca(sizeof(int) * n);
}
在堆栈上分配意味着当堆栈展开时,它将自动被释放


快速说明:正如MacOSX alloca手册页(3)中提到的,“alloca()函数依赖于机器和编译器;它的使用是不允许的。”正如您所知。

有些情况下,与执行的操作相比,分配堆内存非常昂贵。例如,矩阵数学。如果使用较小的矩阵,例如5到10个元素,并进行大量算术运算,malloc开销将非常大。同时,使大小成为编译时常量看起来确实非常浪费和僵化


<>我认为C++本身是不安全的,所以“尝试不添加更多不安全的特征”的论点。另一方面,由于C++是最有运行效率的编程语言特性,它使得它总是有用的:编写性能关键程序的人在很大程度上使用C++,并且它们需要尽可能多的性能。堆块的数量是另一个。允许VLAs作为对象成员是实现这一目标的方法。我正在研究一个建议。当然,这有点复杂,但是它似乎是可行的。

< P> C++允许VLA。它对如何声明VLA提出了一些限制。但是g++允许这样做。

在我自己的工作中,我意识到每当我想要变长自动数组或alloca()之类的东西时,我真的不在乎内存在物理上是否位于cpu堆栈上,只是它来自某个堆栈分配器,不会导致到一般堆的缓慢移动。因此,我有一个每线程对象,它拥有一些内存,可以从中推/弹出可变大小的缓冲区。在某些平台上,我允许通过mmu增加内存。其他平台也有f
template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s;  // equivalently, S<int[n]> s;
template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);