I already know how to create a dynamic 2D matrix using new
and free it using delete
. Since C++ 11 is here with many new memory features such as unique_ptr
, array
container etc.; what is a nice way to create a 2D matrix so that one needs not to free the matrix explicitly using delete
operator?
-
Can you clarify whether the matrix dimensions are konwn at compile-time? – M.M Oct 02 '15 at 21:34
-
Yes they are known at compile time. – aghost Oct 02 '15 at 21:36
3 Answers
One of the simplest ways is to use a vector of vectors
const int N = 10;
const int M = 10;
vector<vector<int>> matrix2d(N, vector<int>(M, 0)); // 10x10 zero-initialized matrix
matrix2d[0][0] = 42;
You could of course use a single vector and wrap it into an accessor class
vector<int> matrix(N * M, 0) // Ditto as above, but needs stride-aware accessors
I'll post a small example here for completeness' sake
template <typename T>
class Matrix2D {
std::vector<T> data;
unsigned int sizeX, sizeY;
public:
Matrix2D (unsigned int x, unsigned int y)
: sizeX (x), sizeY (y) {
data.resize (sizeX*sizeY);
}
T& operator()(unsigned int x, unsigned int y) {
if (x >= sizeX || y>= sizeY)
throw std::out_of_range("OOB access"); // Throw something more appropriate
return data[sizeX*y + x]; // Stride-aware access
}
};
or perhaps combine your way with a smart pointer. Notice that the vector<vector<int>>
approach should be used with caution since the vectors are independent from each other and there's nothing to enforce that they should keep their size fixed.

- 43,032
- 26
- 132
- 246
-
3It would be better use a single vector `vector
matrix_data(N * M, 0)` wrapped by a class with 2d accessors – Andrey Nasonov Oct 02 '15 at 21:09 -
I'll propose that as another solution. This has the advantage of being easy to understand and use although it's definitely suboptimal. – Marco A. Oct 02 '15 at 21:10
-
Since I saw many approaches above, it just came to my mind that if the following approach is memory leak safe. #include
#include – aghost Oct 02 '15 at 22:01using namespace std; int main() { size_t N = 10, M = 4; vector< vector > my_arr(N); for(unsigned i = 0; i < N; i++) my_arr[i] = vector (M); for(unsigned i = 0; i < N; i++) { for(unsigned j = 0; j < M; j++) cout << my_arr[i][j] << " "; cout << endl; } return 0; } -
1@AnirbanGhosh using `std::vector` is memory-leak safe since the container manages the allocation and deallocation for you. – Marco A. Oct 02 '15 at 22:06
-
I strongly suggest using array_view
from the GSL, which will eventually be part of the standard.
#include <array>
#include <vector>
#include "array_view.h" // must be manually imported until standardization
int main()
{
std::array<int, 10> arr{}; // 10 ints on the stack
std::vector<int> vec{12}; // 12 ints on the heap
auto a = gsl::array_view<int, 2>{{2, 5}, arr}; // 2D, 2x5 matrix
auto b = gsl::array_view<int, 3>{{3, 2, 2}, vec}; // 3D, 3x2x2 matrix
auto c = gsl::array_view<int>{vec}; // 1D, spans from `begin()` to `end()`
a[{0,3}] += b[{0,1,1}] * -c[2]; // access syntax
}
N.B. array_view
holds no control over the lifetime of the range it looks at. See here for full details.
Edit:
array_view is dead as it was becoming too complicated in handling multidimensional arrays with zero cost abstraction. You should instead use span from the GSL.
See this for more information about span.

- 347
- 3
- 13

- 4,250
- 1
- 16
- 37
-
N.b. this question is tagged with C++11. Not sure if OP can make use of this. – Marco A. Oct 02 '15 at 21:15
-
@Marco GSL supports C++11 as it's a header-only library, it's just one include away. I feel it's important to have a forward-looking solution for the question as well, since this will be in the standard eventually. – Brian Rodriguez Oct 02 '15 at 21:16
-
-
2`array` must have size known at compile-time. OP was unclear but I think he means that the size may not be known until runtime – M.M Oct 02 '15 at 21:33
-
@M.M Well, as long as the rank doesn't change (if it did, it would require a different type for most approaches anyway) one could emulate dynamic sizes by changing the bounds of the `array_view`. Also, `array_view` works with _any_ contiguous sequence, _including vectors_ (so runtime changes are possible). – Brian Rodriguez Oct 02 '15 at 21:38
-
@M.M The OP was later clarified in the comments. The size is known at compile time. – Fantastic Mr Fox Oct 02 '15 at 21:53
Based on above answers, I have found a simple way to create matrices although not using C++11 features. Here is an illustration.
#include <iostream>
#include <vector>
using namespace std;
typedef vector<vector<int>> Matrix2D;
typedef vector<Matrix2D> Matrix3D;
Matrix2D my_arr;
int main()
{
const size_t N = 9;
for(unsigned s = 4; s <= N; s++)
{
my_arr.resize(s);
for(unsigned i = 0; i < s; i++)
my_arr[i].resize(s,s);
for(unsigned i = 0; i < s; i++)
{
for(unsigned j = 0; j < s; j++)
cout << my_arr[i][j] << " ";
cout << endl;
}
cout << "\n\n";
}
return 0;
}

- 235
- 2
- 12
-
Considering you want to use an array known at compile time, using a `std::vector` is a bad idea. You should use at least use a `std::array` instead. I still, however, strongly suggest using my answer. – Brian Rodriguez Oct 03 '15 at 14:58
-
Thanks. I am wondering if the array container can be resized when required like vectors. – aghost Oct 03 '15 at 15:04
-
1No they can't, but in that case you never wanted a compile-time array in the first place. Compile-time means it will never change, which is why `std::array` would be preferred. Otherwise `std::vector` would be the way to go. However, you should still place it _flatly_, because otherwise you'll suffer from locality issues. (vector of vector of vector of ints (3D matrix) means **3** pointer dereferences when only 1 is necessary. This _will_ bite you back as you make and iterate over bigger matrices) – Brian Rodriguez Oct 03 '15 at 15:34
-
I see your point. Thank you very much. I will try to follow your approach then. – aghost Oct 03 '15 at 16:26
-
1Since this is basically my answer it would be nice to be awarded some points. – Marco A. Oct 03 '15 at 17:37