0

I wish to initialize a multidimensional, dynamic array inside a class. But, I am getting an error.

I have seen several examples on the net. They seem to be difficult. I am new to coding. I would like a simple solution if possible.

class myp
{
    int ntc = 5;
    public:
    double** y = new double*[ntc];
    for(int i = 0; i < ntc; ++i)
        y[i] = new int[3];
};
int main()
{
    int x;
    myp mp;
    mp.y[1][1] = 3;
    cout<<mp.y[1][1]<<endl;;
    return 0;
}

test.cpp:12:2: error: expected unqualified-id before ‘for’
  for(int i = 0; i < ntc; i++)
  ^~~
test.cpp:12:17: error: ‘i’ does not name a type
  for(int i = 0; i < ntc; i++)
             ^
test.cpp:12:26: error: ‘i’ does not name a type
  for(int i = 0; i < ntc; i++)
Makyen
  • 31,849
  • 12
  • 86
  • 121

2 Answers2

2

You need to do class initialisation in the constructor function, and cleanup in the destructor.

class myp
{
  int m_numColumns;
  int m_numRows;
  double** y;
public:

  // overload array operators
  double* operator [] (size_t row) { return y[row]; }
  const double* operator [] (size_t row) const { return y[row]; }

  // return dimensions of array
  int numColumns() const { return m_numColumns; }
  int numRows() const { return m_numRows; }

  // constructor
  myp(int nc, int nr) : m_numColumns(nc), m_numRows(nr)
  {
    y = new double*[m_numRows];

    for(int i = 0; i < m_numColumns; ++i)
      y[i] = new int[m_numColumns];
  }

  // destructor
  ~myp()
  {
    for(int i = 0; i < m_numColumns; ++i)
      delete [] y[i];
    delete [] y;
  }

  // be careful of the copy ctor. I'm deleting it in this case!
  myp(const myp&) = delete;

  // edit: as per user4581301's suggestion
  myp() = delete;
  myp(myp&&) = delete; // remove move ctor
  myp& operator = (const myp&) = delete; // remove assignment
  myp& operator = (myp&&) = delete; // remove move assignment
};

int main()
{
   myp mp(5, 3);
   mp[1][1] = 3;
   cout << mp[1][1]<<endl;
   return 0;
}
robthebloke
  • 9,331
  • 9
  • 12
  • If you want to, you can omit deleting the move constructor and move assignment operator. No implicit move constructor or move assignment is created if a user-defined copy constructor is supplied. Deleting the copy constructor counts as supplying. – user4581301 May 16 '19 at 00:38
  • Yeah, however it's probably better for the OP to realise there may be a few more methods to implement if they want to build a complete 2D dynamic array type. – robthebloke May 16 '19 at 00:55
  • Agreed. That doesn't mean much coming from me, [fortunately Scott Meyers' opinion carries some hefty weight.](http://scottmeyers.blogspot.com/2014/03/a-concern-about-rule-of-zero.html) Side note: One other bit of nastiness in this type of matrix is it allows self destructive behaviours like `delete[] myMatrix[x];` or `myMatrix[x] = nullptr;` It's also kind of slow because of pointer chasing and the resulting bad cache behaviour when used with a small matrix. – user4581301 May 16 '19 at 01:03
0

Just For Run.

class myp 
{
    int ntc = 5;
public:
    double **y;

    void initArray()
    {   
        y = new double*[ntc];
        for(int i = 0; i < ntc; ++i)
            y[i] = new double[3]; // i change this line [new int] to [new double]tv
    }   
};

int main()
{
    int x;
    myp mp; 
    mp.initArray();
    mp.y[1][1] = 3;
    cout<<mp.y[1][1]<<endl;;
    return 0;
}

using constructor & destructor

class myp 
{   
    int ntc = 5;
public:  
    double **y;

    myp() // run at created
    {
        y = new double*[ntc];   
        for(int i = 0; i < ntc; ++i)
            y[i] = new double[3];
    }

    ~myp() // run at the end of life cycle 
    {   
        /* free memory here */
    }

};

int main()  
{  
    int x;  
    myp mp;  // myp() called
    mp.y[1][1] = 3;  
    cout<<mp.y[1][1]<<endl;  
    return 0;  
}  

using constructor with parameter, for dynamic size

class myp 
{   
    //    int ntc = 5;  // using at created
public:  
    double **y;

    myp(int ntc, int size) // run at created
    // if you want to use only myp mp;
    // myp(int ntc = 5, int size = 3) {} will be helpful
    {
        y = new double*[ntc];   
        for(int i = 0; i < ntc; ++i)
            y[i] = new double[size];
    }

    ~myp() // run at the end of life cycle 
    {   
        /* free memory here */
    }

};

int main()  
{  
    int x;  
    myp mp(5, 3);  // myp(int, int) called
    mp.y[1][1] = 3;  
    cout<<mp.y[1][1]<<endl;  
    return 0;  
}  

Makyen
  • 31,849
  • 12
  • 86
  • 121
Zem
  • 464
  • 3
  • 14
  • The first supplied option is a bad, bad idea. It doesn't destruct and allows the creation of an object that is a time-bomb. Please promote [RAII-based solutions](https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii) where possible. Also, humans have an annoying habit of latching onto the first option they're given. If that first option sucks, odds are good they're going to write sucky code. The second option ignores the [Rules of Three and Five](https://en.cppreference.com/w/cpp/language/rule_of_three), often resulting in another time-bomb. – user4581301 May 16 '19 at 00:47
  • Ditto the third option. Finally, the answer does not explain what went wrong. – user4581301 May 16 '19 at 00:48