int[n][m], where n and m are known at runtime

后端 未结 3 1671
别那么骄傲
别那么骄傲 2021-01-13 13:34

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 arr(n * m);
         


        
3条回答
  •  余生分开走
    2021-01-13 13:51

    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(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 > arr(n, std::vector(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 
    class vector2d {
    
        int n_;
        int m_;
        std::vector vec_;
    
        template 
        class vector2d_ref {
            typedef std::iterator_traits TRAITS;
            typedef typename TRAITS::value_type R_TYPE;
            template  friend class vector2d;
            I p_;
            vector2d_ref (I p) : p_(p) {}
        public:
            R_TYPE & operator [] (int j) { return *(p_+j); }
        };
    
        typedef std::vector VEC;
        typedef vector2d_ref REF;
        typedef vector2d_ref CREF;
    
        template  
        vector2d_ref 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 v(n, m);
        v[i][j] = 7;
        std::cout << v[i][j] << '\n';
    

提交回复
热议问题