I am trying to do something like this:
std::string* Plane = new std::string[15][60];
However this code seems not to compile. Is there any other way to accomplish the same result? Thanks for any potential help.
I am trying to do something like this:
std::string* Plane = new std::string[15][60];
However this code seems not to compile. Is there any other way to accomplish the same result? Thanks for any potential help.
When using new[]
to allocate a multi-dimensional array, you have to allocate each dimension separately, eg:
std::string** Plane = new std::string*[15];
for(int i = 0; i < 15; ++i)
Plane[i] = new std::string[60];
...
for(int i = 0; i < 15; ++i)
delete[] Plane[i];
delete[] Plane;
To access a string at a given row/column pair, you can using Planes[row][column]
syntax.
Otherwise, flatten it into a 1-dimensional array instead:
std::string* Plane = new std::string[15*60];
...
delete[] Plane;
To access a string at a given row/column pair, you can using Planes[(row*60)+column]
syntax.
That being said, you should stay away from using raw pointers like this. Use std::vector
or std::array
instead:
typedef std::vector<std::string> string_vec;
// or, in C++11 and later:
// using string_vec = std::vector<std::string>;
std::vector<string_vec> Planes(15, string_vec(60));
// C++11 and later only...
std::vector<std::array<std::string, 60>> Planes(15);
// C++11 and later only...
using Plane_60 = std::array<std::string, 60>;
std::unique_ptr<Plane_60[]> Planes(new Plane_60[15]);
// C++14 and later only..
using Plane_60 = std::array<std::string, 60>;
std::unique_ptr<Plane_60[]> Planes = std::make_unique<Plane_60[]>(15);
Any of these will let you access strings using Planes[row][column]
syntax, while managing the array memory for you.
There's three ways of doing this.
The first is to allocate it as an 'array of arrays' structure (I'm converting your code to std::vector
, because it's way safer than dealing with raw pointers). This is ideal if you need each row to have its own length, but eats up extra memory:
std::vector<std::vector<std::string>> Plane(15);
for(size_t index = 0; index < 15; index++)
Plane[index].resize(60);
for(size_t i = 0; i < 15; i++)
for(size_t j = 0; j < 60; j++)
Plane[i][j] = "This is a String!";
The second is to allocate it as a flat structure, which dramatically improves performance at the cost of reduction of flexibility:
std::vector<std::string> Plane(15 * 60);
for(size_t i = 0; i < 15; i++)
for(size_t j = 0; j < 60; j++)
Plane[i* 60 + j] = "This is a String!";
The third, which I consider the best option by far because of its extensibility, is to roll a Matrix
class which abstracts away these details for you, making it less likely you'll make a mistake in your coding:
template<typename T>
class Matrix {
std::vector<T> _data;
size_t rows, columns;
public:
Matrix(size_t rows, size_t columns) : rows(rows), columns(columns), _data(rows * columns) {}
T & operator()(size_t row, size_t column) {
return _data[row * columns + column];
}
T const& operator()(size_t row, size_t column) const {
return _data[row * columns + column];
}
};
Matrix<std::string> Plane(15, 60);
for(size_t i = 0; i < 15; i++)
for(size_t j = 0; j < 60; j++)
Plane(i, j) = "This is a String!";
Of course, that's an extremely simplified implementation; you'd probably want to add a bunch of STL-like functionality like rows()
, columns()
, at()
, begin()
, end()
, etc.