简体   繁体   中英

What is the correct way to declare multi-dimensional array inside C++ class

It is always frustrating when I try to declare an array in C++. Maybe I just do not understand how array works. The following situation is I am writing a constructor which initializes the row, col, and multi-dimensional array. The code runs into an error.

I already declared both row, col, and array variables in the private class members. When I run the main, the row and col will pass into constructor. The array should be initialized successfully?

#include <bits/stdc++.h>
using namespace std;

class SpreadSheet {
private:
  int r, c;
  string table[r][c];

public:
  SpreadSheet(int row, int col) {
    r = row; c = col;

    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        table[i][j] = ' ';
      }
    }
  }
};

int main() {
  SpreadSheet t(3, 3);

  return 0;
}

Below is the error log I got. I guess I understand the basic logic behind it. The array size has to be assigned before compiling the code. So what is the correct way around this problem?

demo.cc:7:16: error: invalid use of non-static data member ‘SpreadSheet::r’
    7 |   string table[r][c];
      |                ^
demo.cc:6:7: note: declared here
    6 |   int r, c;
      |       ^
demo.cc:7:19: error: invalid use of non-static data member ‘SpreadSheet::c’
    7 |   string table[r][c];
      |                   ^
demo.cc:6:10: note: declared here
    6 |   int r, c;
      |          ^
demo.cc: In constructor ‘SpreadSheet::SpreadSheet(int, int)’:
demo.cc:15:9: error: ‘table’ was not declared in this scope
   15 |         table[i][j] = ' ';
      |
string table[r][c];

is invalid, as the compiler has already let you know.

r and c must be known at compile time for you to be able use them to declare an array.

You can use

std::vector<std::vector<std::string>> table;

and make sure to initialize it appropriately in the constructor of the class.

SpreadSheet(int row, int col) : table(row, std::vector<std::string>(col, " "))
{
 ...
}

If you use that, there is no need for the member variables r and c . Number of rows can be obtained by using table.size() and number of columns can be obtained using table[0].size() if number of rows is greater than zero.

The posted code for the class can be simplified to

class SpreadSheet {
  private:
    std::vector<std::vector<std::string>> table;

  public:
    SpreadSheet(int row, int col) : table(row, std::vector<std::string>(col, " ")) {}
};

VLAs (Variable Length Arrays) are not supported in C++ (and should not be used anyway in C).

The size of a variable must be known at compile-time, which implies you cannot define objects with unknown size (at compile-time), like the class in your example.

If you want a "dynamic array", use the standard std::vector . In particular, if you have a rectangular table, the best approach is to declare a:

std::vector<std::string> table;

And initialize/resize it for r * c elements.

I wouldn't use a C style array like x[r][c] . The better solution is vector of vector as described in the answer by R Sahu.

However if you really want to use a C-style array, you can use a template like:

template <int r, int c> class SpreadSheet 
{
    string table[r][c];
};

int main() {
    SpreadSheet<3, 3> t;
    ...

Another solution would be a pointer instead of an array.

   class SpreadSheet {
private:
  int r, c;
  string **table;

public:
  SpreadSheet(int row, int col) {
    r = row; c = col;

    table = new string*[r];
    for (int i = 0; i < r; ++i)
    {
        table[i] = new string[c];
    }

    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        table[i][j] = ' ';
      }
    }
  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM