的INT [n] [M],其中n和m是在运行时已知 [英] int[n][m], where n and m are known at runtime

查看:142
本文介绍了的INT [n] [M],其中n和m是在运行时已知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常需要创建宽度和高度的二维数组(让他们成为n和m),在编译时未知的,平时我写的:

 矢量<&INT GT; ARR(N * M);

和我手动访问元素有:

 改编[J * M + 1]

最近我告诉我可以代替写:

  INT ARR [N] [M] // n和m仍然只在运行时称。

因此​​,这里有2个问题:


  1. 这是由行为的C ++标准?
  2. 允许
  3. 我应该如何传递这样一个数组功能? G ++报道,改编的类型为 INT(*)[N] ,但同样,n是动态的,在声明之外的功能尚不清楚()。


解决方案

则是问有关(其中尺寸仅取得在运行时知道)的特点是非标准扩展的C ++,但C的一个标准99(在C.11做成一个可选功能)。 (VLA)该功能被称为变长数组,链接是GCC的文档。

如果你正在使用gcc,那么你传递数组的长度作为参数传递给函数。

 无效美孚(INT男,INT ARR [] [M]){
    // ...
}

然而,似乎有在任的编译器或文件中的错误,因为编译C code时,上面的函数原型语法只适用,不C ++(截至gcc版本4.8.2)。唯一的解决方法,我发现是使用无效* 参数,然后将其丢诠释函数体:

  INT foo_workaround(INT男,无效* X)
{
    INT(* ARR)[M] =的static_cast< INT(*)[M] GT;(x)的;
    // ...
}

有其他的解决办法,如果你不希望依赖于编译器扩展。如果你不介意为每行一个单独的配置,你可以用向量的载体,例如:

 的std ::矢量<的std ::矢量<&INT GT; > ARR(N,性病::矢量<&INT GT;(M));

不过,如果你想有一个单一的分配块就像你在你自己的例子证明,那么最好是创建一个围绕矢量给你2-D的包装类喜欢的语法。

 模板< typename的T>
一流的Vector2D {    INT N_;
    INT M_;
    的std ::矢量< T> vec_;    模板< typename的I>
    类vector2d_ref {
        的typedef的std :: iterator_traits< I>性状;
        的typedef typename的性状:: value_type的R_TYPE;
        模板< typename的>友元类的Vector2D;
        我P_;
        vector2d_ref(I P):P_(p)的{}
    上市:
        R_TYPE&安培;运算符[](诠释J){返回*(P_ + J); }
    };    的typedef的std ::矢量< T> VEC;
    typedef的vector2d_ref< typename的VEC:迭代> REF;
    typedef的vector2d_ref< typename的VEC ::为const_iterator> CREF;    模板< typename的I>
    vector2d_ref< I> REF(I P,int i)以{返回P +(我* M_); }上市:    的Vector2D(INT N,INT M):N_(N),M_(M),vec_(N * M){}
    REF操作符[](int i)以{返回REF(vec_.begin(),I); }
    CREF的operator [](int i)以常量{返回REF(vec_.begin(),I); }};

该包装的运算符[] 返回一个中间对象也重载运算符[] 允许2维数组使用时,包装语法。

 的Vector2D< INT> V(N,M);
    v [I] [J] = 7;
    性病::法院LT&;< v [i] [j]的<<的'\\ n';

I often need to create a 2D array with width and height (let them be n and m) unknown at compile time, usually I write :

vector<int> arr(n * m);

And I access elements manually with :

arr[j * m + i] 

I recently got told that I could instead write :

int arr[n][m] // n and m still only known at runtime.

So here are 2 questions :

  1. Is this behaviour allowed by the C++ Standard ?
  2. How should I pass such an array to a function ? g++ reports that arr has type int (*)[n], but again, n is dynamic and not known outside the function where it is declared (main).

The feature you are asking about (where the dimensions are only made known at runtime) is a non-standard extension of C++, but a standard one of C.99 (made into an optional feature in C.11). The feature is called variable-length array (VLA), and the link is the documentation for GCC.

If you are using GCC, then you are to pass the length of the array as a parameter to the function.

void foo (int m, int arr[][m]) {
    //...
}

However, there seems to be a bug in either the compiler or the documentation, as the above function prototype syntax only works when compiling C code, not C++ (as of gcc version 4.8.2). The only work-around I found was to use a void * parameter, and cast it int the function body:

int foo_workaround (int m, void *x)
{
    int (*arr)[m] = static_cast<int (*)[m]>(x);
    //...
}

There are other solutions if you do not want to rely on a compiler extension. If you don't mind a separate allocation for each row, you can use a vector of vectors, for example:

std::vector<std::vector<int> > arr(n, std::vector<int>(m));

However, if you want a single allocation block like you demonstrated in your own example, then it is better to create a wrapper class around vector to give you 2-d like syntax.

template <typename T>
class vector2d {

    int n_;
    int m_;
    std::vector<T> vec_;

    template <typename I>
    class vector2d_ref {
        typedef std::iterator_traits<I> TRAITS;
        typedef typename TRAITS::value_type R_TYPE;
        template <typename> friend class vector2d;
        I p_;
        vector2d_ref (I p) : p_(p) {}
    public:
        R_TYPE & operator [] (int j) { return *(p_+j); }
    };

    typedef std::vector<T> VEC;
    typedef vector2d_ref<typename VEC::iterator> REF;
    typedef vector2d_ref<typename VEC::const_iterator> CREF;

    template <typename I> 
    vector2d_ref<I> ref (I p, int i) { return p + (i * m_); }

public:

    vector2d (int n, int m) : n_(n), m_(m), vec_(n*m) {}
    REF operator [] (int i) { return ref(vec_.begin(), i); }
    CREF operator [] (int i) const { return ref(vec_.begin(), i); }

};

The wrapper's operator[] returns an intermediate object that also overloads operator[] to allow 2-dimensional array syntax when using the wrapper.

    vector2d<int> v(n, m);
    v[i][j] = 7;
    std::cout << v[i][j] << '\n';

这篇关于的INT [n] [M],其中n和m是在运行时已知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆