堆栈上的C ++可变长度数组

时间:2014-05-09 16:02:48

标签: c++ arrays

我刚刚遇到项目dcraw中导致Visual Studio 2012编译器失败的代码。它的形式如下:

void CLASS cubic_spline (const int *x_, const int *y_, const int len)
{
  float A[2*len][2*len], b[2*len], c[2*len], d[2*len];
  ...

问题是在堆栈上创建这些可变长度数组。我从来没有真正看到这样的代码 - 是否可以在Visual Studio编译器中编译它?

3 个答案:

答案 0 :(得分:2)

有允许这样做的有效编译器扩展(例如Clang's oneGCC's one),但它不是标准的。

在C ++ 11中,如果数值恒定,您还可以使用constexpr。最后提交了a proposal来标准化它。

如果x_y_是数组,您只需使用std::array,如下所示:

template<std::size_t size>
void CLASS cubic_spline (std::array<int, size> const& x, std::array<int, size> const& y)
{
    using float_array = std::array<float, 2 * size>;
    std::array<float_array, 2 * size> A;
    float_array b, c, d;
    // ...
}

这样,您可以在编译时确保传递的数组维度相等。

否则,您可以使用std::vector清除它:

void CLASS cubic_spline (std::vector<int> const& x, std::vector<int> const& y)
{
    std::vector<std::vector<float>> A(2 * x.size());
    std::vector<float> b, c, d;
    // ...
}

答案 1 :(得分:2)

如前所述,VLA(可变长度数组)是一个C功能,更重要的是Visual Studio不支持的C99功能。在Linux上,Clang和Gcc都支持C99(我认为是C11)并允许在C ++中使用这种语法作为扩展。

在C ++中,您可以通过切换到所有简单数组的std::vector<float>来轻松转换代码。只有A才需要更多工作:

  • 你可以使用std::vector< std::vector<float> >,但是你会失去邻居和地点
  • 或者您可以使用展平版std::vector<float> A(2*len*2*len);,但您将失去A[i][j]的访问权限,而A[i*2*len + j]必须转换为<{1}}

在任何情况下,您都需要更新此代码以使其在Visual Studio上运行。

编辑:根据您的评论:

  

该函数在代码中调用两次,一次调用cubic_spline(cx, cf, 9);,一次调用cubic_spline(cx, cf, 18);。在第一个示例中,cxcyint[9],在第二个示例中,他们为int[18]

在这种情况下,您实际上可以将该功能设为模板:

template <size_t len>
void CLASS cubic_spline(int const (&x)[len], int const (&y)[len]) {
    float A[2*len][2*len], b[2*len], c[2*len], d[2*len];
}

请注意,我删除了最后一个参数,因为不再需要它。 xy的类型为int const (&)[len],它是int const长度为len的数组的引用。

答案 2 :(得分:1)

这是特定于GCC的编译器扩展,请参阅Arrays of Variable Length。我不知道任何编译器选项使它们在VC中开箱即用。如果这是一个非常孤立的问题,请尝试使用预处理器#ifdef来向VC提供不同的代码。