C ++中的数组在具有不同长度的堆栈上进行分配

时间:2013-07-31 11:55:10

标签: c++ visual-c++ g++ clang

我很惊讶地发现可以在C ++中在堆栈上分配变长数组(例如int array[i];)。它似乎在clang和gcc(在OS / X上)都能正常工作,但是MSVC 2012不允许它。

这个语言功能叫什么?它是官方的C ++语言功能吗?如果是,那么哪个版本的C ++?

完整示例:

#include <iostream>

using namespace std;

int sum(int *array, int length){
    int s = 0;
    for (int i=0;i<length;i++){
        s+= array[i];
    }
    return s;
}

int func(int i){
    int array[i]; // <-- This is the feature that I'm talking about
    for (int j=0;j<i;j++){
        array[j] = j;
    }

    return sum(array, i);

}

int main(int argc, const char * argv[])
{
    cout << "Func 1 "<<func(1)<<endl;
    cout << "Func 2 "<<func(2)<<endl;
    cout << "Func 3 "<<func(3)<<endl;

    return 0;
}

4 个答案:

答案 0 :(得分:6)

此功能称为可变长度数组或VLA。

它是C99标准(以及C11)的一部分,但C ++ 11不支持。但是,如您所见,某些编译器会将其视为扩展名。

最后,类似的功能(但与C99的VLA不完全相同)在布里斯托尔的C ++委员会会议上得到批准(2013年4月),并且在C ++ 14的current draft中。

C99的VLA和C ++ 14之间的两个主要区别如下所示:

void f(std::size_t n) {
    int a[n];
    unsigned int x = sizeof(a);
    // ...
    int matrix m[n][n];
}    

在C99中,表达式sizeof(a)在运行时进行计算。在C ++ 14中,这是非法的。此外,C ++ 14不支持多维VLA。

有关C99的VLA的更多信息,请参阅this DrDobb的文章。

有关C ++ 14运行时大小数组的更多信息,请参阅N3639,这是布里斯托尔批准的论文。

更新:在Chigago会议上,委员会决定从C ++ 14中删除此功能,而是将其放在单独的文档中,Technical Specification (TS) on array Extendions(TS)。此外,TS还包括模板类dynarray,它与运行时边界的数组有些相关。

从C ++ 14中删除它的主要原因是委员会希望在标准化这些功能之前从实现和用户体验中获得反馈。

答案 1 :(得分:5)

你在看GCC的variable length arrays。这是一个GNU扩展,不是标准的C ++。

答案 2 :(得分:2)

这是一个gcc extension,看起来clang supports this in limited cases它不是标准的C ++,尽管它是valid c99。在gccclang,您可以使用-pedantic标记,它会在gcc中向您发出如下警告:

warning: ISO C++ forbids variable length array ‘array’ [-Wvla]

clang中的相似:

warning: variable length arrays are a C99 feature [-Wvla-extension]

答案 3 :(得分:1)

在某些情况下,您可以使用constexpr(C ++ 11)作为解决方法:

constexpr int getArraySize (int factor) {
    return 2 * factor + 1;
}

int my_array[getArraySize(3)];

实际上在C ++ 14中,此限制不应再存在:http://isocpp.org/blog/2013/04/n3639-runtime-sized-arrays-with-automatic-storage-duration