[ACCEPTED]-Is there a way to initialize an array with non-constant variables? (C++)-arrays

Accepted answer
Score: 15

use vector.

#include <vector>
class YourClass
{
public:
    YourClass()
    : x(read_x_from_file()), y(read_y_from_file())
    {
        my_array.resize(x);
        for(int ix = 0; ix < x; ++ix)
            my_array[ix].resize(y);
    }

    //stuff

private:
    int x, y;
    std::vector<std::vector<char> > my_array;
};

0

Score: 10

The compiler need to have the exact size 7 of the class when compiling, you will have 6 to use the new operator to dynamically allocate 5 memory.

Switch char array[x][y]; to char** array; and 4 initialize your array in the constructor, and 3 don't forget to delete your array in the 2 destructor.

class MyClass
{
public:
    MyClass() {
        x = 10; //read from file
        y = 10; //read from file
        allocate(x, y);
    }

    MyClass( const MyClass& otherClass ) {
        x = otherClass.x;
        y = otherClass.y;
        allocate(x, y);

        // This can be replace by a memcopy
        for( int i=0 ; i<x ; ++i )
            for( int j=0 ; j<x ; ++j )
                array[i][j] = otherClass.array[i][j];
    }

    ~MyClass(){
        deleteMe();
    }

    void allocate( int x, int y){
        array = new char*[x];
        for( int i = 0; i < y; i++ )
            array[i] = new char[y];
    }

    void deleteMe(){
        for (int i = 0; i < y; i++)
           delete[] array[i];
        delete[] array;
    }

    MyClass& operator= (const MyClass& otherClass)
    {
        if( this != &otherClass )
        {
            deleteMe();
            x = otherClass.x;
            y = otherClass.y;
            allocate(x, y);
            for( int i=0 ; i<x ; ++i )
                for( int j=0 ; j<y ; ++j )
                    array[i][j] = otherClass.array[i][j];            
        }
        return *this;
    }
private:
    int x, y;
    char** array;
};

*EDIT: I've had the copy constructor and 1 the assignment operator

Score: 4

Not in that manner, as in c++, c-style array 8 sizes have to be known at compile time, with 7 some vendor specific extensions allowing 6 certain runtime sizes (to enhance compatibility 5 with C99), but not in the situation you 4 are describing (if you are interested, here's a description). The 3 easiest thing to do would be:

std::vector< std::vector<char> > array;

And apply the 2 size in the constructor:

array.resize(x);
for(std::vector< std::vector<char> >::iterator curr(array.begin()),end(array.end());curr!=end;++curr){
   curr->resize(y);
}

There are many advantages 1 of vector over c style arrays, see here

Score: 2

Put all the memory into one block.
Because 3 it is private you can then get your access 2 methods to retrieve the correct value.

Quick 1 example:

#include <vector>
#include <iostream>

class Matrix
{
    public:
    class Row
    {
        public:
        Row(Matrix& p,unsigned int x)
            :parent(p)
            ,xAxis(x)
        {}
        char& operator[](int yAxis)
        {
            return parent.data(xAxis,yAxis);
        }
        private:
            Matrix&         parent;
            unsigned int    xAxis;
    };

    Matrix(unsigned int x,unsigned int y)
        :xSize(x)
        ,ySize(y)
        ,dataArray(x*y)
    {}

    Matrix::Row operator[](unsigned int xAxis)
    {
        return Row(*this,xAxis);
    }
    char& data(unsigned int xAxis,unsigned int yAxis)
    {
        return dataArray[yAxis*xSize + xAxis];
    }
    private:
        unsigned int xSize;
        unsigned int ySize;
        std::vector<char>   dataArray;
};


int main()
{
    Matrix      two(2,2);

    two[0][0]   = '1';
    two[0][1]   = '2';
    two[1][0]   = '3';
    two[1][1]   = '4';

    std::cout <<  two[1][0] << "\n";
    std::cout <<  two.data(1,0) << "\n";
}
Score: 2

Take a look at boost::multi_array.

0

Score: 1

You can't allocate or initialize a global 9 or static array declaratively using non-constant 8 values (compile-time). It's possible for 7 local arrays though (C99 variable sized 6 arrays, as their initializer essentially 5 runs at runtime every time the function 4 is executed).

For your situation, I suggest 3 using a pointer instead of an array and 2 create the actual array dynamically at runtime 1 (using new):

class CLASS
{
public:
    CLASS(int _x, int _y) : x(_x), y(_y) {
       array = new char*[x];
       for(int i = 0; i < x; ++i)
           array[i] = new char[y];
    }
    ~CLASS() {
       for (int i = 0; i < x; ++i)
           delete[] array[i];
       delete[] array;
    }
    //stuff
private:
    int x, y;
    char **array;
};
Score: 1

You can allocate memory to your 2-dimensional 2 array in the constructor and free it in 1 the destructor. The simplest way:

array = (char **)malloc(sizeof(char *) * x);
if (array) {
    for (i = 0; i < x; i++) {
        array[i] = (char *)malloc(sizeof(char) * y);
        assert(array[i]);
    }
}
Score: 0

If the size is not known at compile time, the 3 array is dynamic. What you could do to keep 2 it static is to make them larger than your 1 largest expected size.

Score: 0

If you want a dynamically sized array as 6 a class member, you need to array new it and 5 assign that value to a pointer. The char array[size] syntax 4 is only for statically-sized arrays.

Better yet, you 3 really should use an std::vector< std::vector<char> >, there are very few 2 good reasons to manually work with dynamically 1 sized arrays these days.

More Related questions