Reference Arrays/Matrices in C++ - c++

I am new to C++ which is the reason why I'm currently kind of stuck.
Now here's the Problem: I have a couple of float matrices like this:
static const float matr1[4][8] = {0.0, 0.0, ...};
static const float matr2[7][8] = {0.0, 0.5, ...};
etc.
I have a struct like to this one:
struct structy{
float matr[][];
int index;
float somevalue;
};
I have a vector of this structy which is created dynamically dependent on other information.
How can I reference a certain of these declared matrices in my struct variable, given that the first parameter of the struct (rows) varies?
I need a row of the matrices as a float array later on.
Thanks for your help!

You should also store the number of columns and the number of rows in structy, so that you know the dimensions of matr at a later point in time. There is no way to check the length of the 2D array otherwise.
As for your main question: Are you having troubles accessing individual matrix entries in one of your 2D float arrays (matr)?

The only way I have ever seen this done is dynamically:
struct structy{
float ** matr;
// Need to add these 2 variables
int dimensionRow;
int dimensionCol;
int index;
float somevalue;
};
When you place the data into matr, you need to also set dimensionRow, and dimensionCol, as well as dynamically allocate matr prior to filling it, IFF you plan to copy. If not you can simply set matr to the pointer of one of your pre-defined matrices. Either way you will need to also set dimensionRow and dimensionCol.

If you need varying sized matrices, I'd suggest using a vector of vectors. This will save you from the trouble of manually allocating a 2D array and managing its memory. One possible implementation:
struct structy {
std::vector< std::vector<float> > matr;
int index;
float somevalue;
};
structy s;
...
s.matr[0][1] = 42.0f;
...
And either grow the vectors on demand using push_back() or grow them beforehand with resize().
Now if you just want a reference to an external matrix (pointer to static memory) then you can just declare a pointer to pointer (double pointer):
struct structy {
const float ** matr;
int index;
float somevalue;
};

You cannot create a reference (not in the traditional sense) that will refer to different types, and arrays with different lengths are different types. However, you can take advantage of the fact that arrays are contiguous, (and so arrays of arrays are contiguous arrays), and create a class that acts as a reference using pointers.
template<typename T>
class matrix_reference
{
public:
template<size_t R, size_t C>
void set_reference(T (&arr)[R][C])
{
m_start = &arr[0][0];
m_rows = R;
m_columns = C;
}
T& operator()(size_t r, size_t c)
{
return m_start[r * m_columns + c];
}
size_t rows() const { return m_rows; }
size_t columns() const { return m_columns; }
private:
T* m_start;
size_t m_rows;
size_t m_columns;
};
int main()
{
matrix_reference<const float> mref;
mref.set_reference(matr1);
for (size_t r=0; r<mref.rows(); ++r)
{
for (size_t c=0; c<mref.columns; ++c)
std::cout << mref(r,c) << ' ';
std::cout << '\n';
}
mref.set_reference(matr2);
for (size_t r=0; r<mref.rows(); ++r)
{
for (size_t c=0; c<mref.columns; ++c)
std::cout << mref(r,c) << ' ';
std::cout << '\n';
}
}

Related

How to declare 2D dynamic array in C++

How to declare a 2D array in which the rows are dynamic but the rows length are fixed? Is there any way to do it without both row and rows length are dynamic?
P.S. I can't use STL containers or class string.
You can use std::vector and std::array for this.
std::vector is a dynamic-length array.
std::array is a fixed-length array, used as
array<int, 20> arr;
arr[10] = 42;
array<int, 20> anotherArr = arr; // copied here, as opposed to C arrays
int oldStyleArr[20];
oldStyleArr[10] = 42;
// int newStyleArr[20] = oldStyleArr; // error here
It is a convenient wrapper over the C-style array, and it provides value semantics and various conveniece methods like size().
So you can create array<vector<int>, 20> for an array of 20 dynamic vectors of ints or vector<array<int, 20>> for a dynamic vector of fixed-length arrays.
UPD: std::array works only with array bounds known at compile-time. If your array bounds are known only at runtime, you still can use std::vector's constructor from size and (optional) element:
int rowCount, columnCount;
cin >> rowCount >> columnCount;
using Row = vector<int>;
// create `vector` of `rowCount` rows,
// where each row is `vector` of `columnCount` ints
vector<Row> arr2d(rowCount, Row(columnCount));
However, that's not the most efficient solution because each row is allocated separately. You can solve this with a little wrapper over one-dimensional vector:
template<class T>
class Vector2D {
public:
Vector2D(int rows, int cols)
: data(rows*cols)
, rows(rows)
, cols(cols) {}
int rowCount() const { return rows; }
int columnCount() const { return cols; }
T& get(int r, int c) { return data[r*cols + c]; }
T const& get(int r, int c) const { return data[r*cols + c]; }
void addRow() {
data.resize(cols*(rows + 1));
}
// ...
private:
vector<T> data;
int rows;
int cols;
};
You can use std::vector for dynamic range arrays. You would want to instantiate a vector of arrays to achieve this.
What you are looking for is probably: std::vector<std::array<int, 20>> arr;
However, if STL containers are not an option you might need to implement the container yourself. A linked list is probably the easiest to implement.
Just declare a 1D array and calculate the index yourself like how compilers generate accesses to a multidimensional array. Each row has width items, so the [x][y] element will have the index x*width + y
template<typename T>
class twoD
{
const int width;
const int height;
T* data;
twoD(int w, int h) : width(w), height(h)
{
data = new T[width*height];
}
~twoD()
{
delete[] data;
}
T& at(int x, int y)
{
return data[x*width + y];
}
T const& at(int x, int y) const
{
return data[x*width + y];
}
}
twoD myArray(4, 8);
myArray.at(2, 3) = 5;
myArray.at(4, 5) = 6 - myArray.at(2, 3);
The same method can be used to access multidimensional arrays in any degree

c++, Object of class changes when creating a new object

I have created a class matrix that besides having some member functions, operators and a constructor has two variables:
int m, which is the dimension (side length) of the quadratic matrix
double a[], which contains the elements of the matrix.
As long as I only create one matrix object A all seem to work fine and all my member operators and functions work as they should.
My problem is that once I create a second object B of the class matrix the variables of object A changes as well.
The relevant code is as follows:
class Matrix{
private:
const int m;
double a[];
public:
Matrix(int inpm);
void fillMatrix(const double inpa[]);
};
Matrix::Matrix(int inpm): m(inpm){
a[impm*inpm];
}
void Matrix::fillmatrix(const double inpa[]){
for (int i ; i<m*m ; i++){
a[i]=inpa[i];
}
}
int min =2;
double ain[min*min] = {1,2,3,4};
double bin[min*min] = {5,6,7,8};
Matrix A(min);
Matrix B(min);
A.fillMatrix(ain);
//A looks precisely as it should here:
//m=2, a={1,2,3,4}
B.fillMatrix(bin);
//Here B looks as it should but A has changed to:
//m=0, a={7,8,3,4}
obviously the change to the first object occur when I run fillMatrix() for the second object but I cannot figure out why, especially since m is a constant integer.
I'm really stuck so grateful for all help.
PS: I use another member function "void printMatrix();" using std:cout to look at the values of m and all elements in a.
a[impm*inpm]; This does not do what you think. GCC even warns with statement has no effect.
a remains uninitialized here and you run into undefined behavior when you try to access a[i]
class Matrix{
private:
const int m;
double *a;
....
and
Matrix::Matrix(int inpm): m(inpm)
{
a = new double[inpm*inpm];
}
and then remember to delete
Matrix::~Matrix()
{
delete a;
}
c++ arrays are not actually allowed to variable. There are plenty of sources about why variable length arrays (vla's) are not allowed. If you wan't a dynamic length array with size chosen at run time, you need to allocate some memory:
double *a;
...
a = new double[inpm*inpm];
But this sucks! Now you have to remember to delete and access correctly and everything. You could wrap this memory in a class to control this, and since this is such a good idea, c++ provides this as standard. It is called std::vector. Your code will happily reduce to this:
class Matrix{
private:
const int m;
std::vector<double> a;
public:
Matrix(int inpm) : m(inpm), a(m * m) {}
The problem is because of your array declaration. people used to call that kind of array declaration as "flexible array declaration.". And it wouldn't work as you expected. plus there are certain rules to follow while using a flexible array.
But if you want to create a dynamic array you can use malloc to create array dynamically.
I've noticed a few issues with your code. The first few were already mentioned by others such as your member double a[]; This is uninitialized and C++ does not allow for variable length vectors. To resolve this there are two possible solutions which I'll discuss shortly. The other issue that others have mentioned is that in your Matrix::fillMatrix() function the variable in your for loop i is also uninitialized, so i can be anything and this will lead to undefined behavior.
A few issues that have not been mentioned by others are as follows:
In your constructor definition you are trying to initialize m with a[impm*inpm] I think this might be a typo on your part. Another one is you declare your function as ::fillMatrix() but you define it outside of the class declaration as ::fillmatrix(). Again I think this might be just a typo on your part.
As for the issue above with the use of arrays in C++ the easiest way to do this is what others have already stated and that is to use std::vector<type>.
The other way is to write a class that works similarly to std::vector but has the mechanics of a matrix. Your class would look something like this using templates: If you want a variable length container at runtime you have to know it's size at compile time using templates here can help as the template has to be deduced at compile time upon instantiation!
template<class T, unsigned N>
class Matrix {
private:
static const unsigned Stride = N;
static const unsigned Size = Stride * Stride;
T data[Size] = {};
public:
Matrix() {};
void fillMatrix( const T* dataIn );
void printMatrix();
};
template<class T, unsigned N>
void Matrix<T, N>::fillMatrix( const T* dataIn ) {
for( unsigned int i = 0; i < Size; i++ ) {
this->data[i] = dataIn[i];
}
}
template<class T, unsigned N>
void Matrix<T, N>::printMatrix() {
for( unsigned int i = 0; i < Stride; i++ ) {
for( unsigned int j = 0; j < Stride; j++ ) {
std::cout << this->data[i*Stride + j] << " ";
}
std::cout << '\n';
}
}
int main() {
// 2x2 = 4
double ain[4] = { 1,2,3,4 };
double bin[4] = { 5,6,7,8 };
Matrix<double, 2> A;
Matrix<double, 2> B;
A.fillMatrix( ain );
A.printMatrix();
std::cout << '\n';
B.fillMatrix( bin );
B.printMatrix();
std::cout << '\n';
// test A again
A.printMatrix();
std::cout << '\n';
B.printMatrix();
std::cout << '\n';
// Try it with other types
// 3x3 = 9
char data[9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
Matrix<char, 3> C;
C.fillMatrix( data );
C.printMatrix();
std::cout << '\n';
return 0;
}
Output:
1 2
3 4
5 6
7 8
1 2
3 4
5 6
7 8
a b c
d e f
g h i
With this type of design using templates you are not restricted to just using a single type such as int, float etc. You can even use User Defined Types. The only thing here that you would need to consider is any kind of operators you may have. Also the way this class is written it will always create a MxM matrix which will always be a square matrix. If you need a non square matrix; you can just add to this class by adding in a 2nd unsigned constant value to the template parameter list and renaming them accordingly for MxN. Then just substitute where they belong in the math. It would look something like this:
template<class T, unsigned M, unsigned N>
class Matrix {
private:
static const unsigned Row = M;
static const unsigned Col = N;
static const unsigned Size = Row * Col;
T data[Size] = {};
};
Now how you label them might depend on if you want Row-Col major or Col-Row major...

Array of a specific size used out of the function it was initialized in

I'm a high school student learning programming and I have a problem that I can't figure out how to solve.
I have an integer "x", and I want a matrix "mat" to have the size of "x":
int mat[x][x];
But that works only in main() where I've read x;
For example if x == 5, the equivalent would be
int mat[5][5];
#include <iostream>
using namespace std;
int x;
int mat[x][x];
void f(int mat2[x][x])
{
}
int main()
{
cin >> x;
int m[x][x];
f(m);
}
I've wrote this short program to show where it works and it doesn't work.
error: array bound is not an integer constant before ']' token
I've the error at the global declaration, at the declaration in function void f. It only compiles without errors in main();
What can I do to create a matrix with the size of x outside of the main function?
Variable length arrays aren't spported in standard c++. Besides you don't want the global definition.
What you can use portably in that case is std::vector:
void f(std::vector<std::vector<int>>& mat)
{
}
int main()
{
cin >> x;
std::vector<std::vector<int>> m(x,std::vector<int>(x));
f(m);
}
If you pass that vector around to functions or being allocated within functions, the size information will be kept at any time.
What can I do to create a matrix with the size of x outside of the main function?
Something like this:
std::vector<std::vector<int>> foo() {
cin >> x;
std::vector<std::vector<int>> m(x,std::vector<int>(x));
return m;
}
int main()
{
std::vector<std::vector<int>> mat = foo();
}
Handling of multi-dimension arrays in C++ is not easy. The best way to go is often to map a multi-dimensionnal indexing with a linear memory chunk.
For instance, for a 2 by 2 matrix, one can create an array of 2*2=4 elements and map it this way:
+-----------+-----------+-----------+-----------+
| map[0][0] | map[0][1] | map[1][0] | map[1][1] |
+-----------+-----------+-----------+-----------+
This seems overly complicated at first glance, but it simplifies greatly the memory allocation.
For an arbitrary sized matrix of width by height, map[i][j] is at index i*height + j. This can be translated in C++, encapsulated in a template class Matrix:
#include <array>
template <typename T, size_t WIDTH, size_t HEIGHT>
class Matrix {
std::array<T, WIDTH*HEIGHT> data;
public:
T& operator()(size_t i, size_t j) {
return data[i*HEIGHT + j];
}
const T& operator()(size_t i, size_t j) const {
return data[i*HEIGHT + j];
}
};
This has the disadvantage that the Matrix' dimensions must be known at compile time (and can be mitigated, see note (ii) at end of answer). But it makes its use so easy:
void fill(Matrix<int, 2, 2>& m) {
m(0,0) = 0;
m(0,1) = 1;
m(1,0) = 2;
m(1,1) = 3;
}
int main() {
Matrix<int, 2, 2> m;
fill(m);
std::cout << m(1,0) << "\n";
}
Note (i): Elements are indexed by (line, column) rather than [line][column] because we can't create an operator[] accepting multiple values.
Live on coliru
Note (ii): This basic idea can be enriched (demo) to handle resizable matrixes, with use of a std::vector instead of std::array and a proxy to std::vector::resize().
Variable-length array is supported by some compiler as an extension. The manual of the compiler provides more information.Gnu VLR
The storage duration of a variable-length array(if supported) generally can't be static, which is why you get the error message (global variables have static storage duration).
Unrelated: The major array bound of the parameter mat2 isn't necessary, i.e. void f(int mat2[x][x]) is equivalent to void f(int mat2[][x]).
C++ has no provision for dynamic 2D matrix but provides all you need to create complex classes. A (static) 2D array is a contiguously allocated array of height arrays of width elements. Just mimic that and:
allocate a linear array of width * height
provide an operator[](int) that returns a pointer to the first element of ith row
do necessary housekeeping in destructor and in a copy (and move if C++11 or above) constructor.
Example of code:
template <typename T>
class Matrix {
T *data;
int width;
int height;
public:
// direct ctor
Matrix(int h, int w): width(w), height(h) {
data = new T[w * h];
}
//copy ctor
Matrix(const Matrix& src): width(src.width), height(src.height) {
data = new T[width * height]; // allocate and copy data array
for (int i=0; i<width * height; i++) data[i] = src.data[i];
}
// move ctor
Matrix(Matrix&& src): width(src.width), height(src.height) {
data = src.data; // steal original array in a move
src.data = NULL; // ensure no deletion will occur at src destruction
}
~Matrix() {
delete data;
data = NULL;
}
// explicitely delete assignement operators
Matrix& operator = (const Matrix&) = delete;
Matrix& operator = (Matrix&&) = delete;
T* operator[](int i) {
//optionaly test 0 <= i < width
return &data[i * width];
}
};
int main()
{
int w;
std::cin >> x;
Matrix<int> m(x, x);
// you can then use m[i][j] as you would for a static 2D array
...
}
This class does not support any resizing by design. If you need that, you really should use a vector<vector<T> >. The downside is that it has no default ctor either, because the dimension must be given at definition time (even if we could easily imagine a 2 phases initialization...).
You can dynamic allocate memory to use, in the c/c++, it does not support dynamic size of static memory allocation, so, you just modify your code like this.
int x;
cin >>x;
int** mat = new int[x][x];

Deleting templated C++ 2-dimensional array

Annoyance over C++'s requirement to pass a dimension in a 2-d array got me working on a templated Matrix class. I've been coding in C# for a bit, so I'm sure I'm a little rusty here.
Issue is, I get a heap exception as soon as I hit the destructor, which is trying to delete the 2-d array.
Any help gratefully accepted!
template <typename T>
class Matrix {
public:
Matrix(int m, int n) : nRows(m), nCols(n) {
pMatrix = new T * [nRows];
for (int i = 0; i < nCols; i++) {
pMatrix[i] = new T[nCols];
}
}
~Matrix() {
if (pMatrix != NULL) {
for (int i = 0; i < nRows; i++) { delete[] pMatrix[i]; }
delete[] pMatrix;
}
}
T ** GetMatrix() const { return pMatrix; }
T * Row(int i) const { return pMatrix[i]; }
inline T Cell(int row, int col) const { return pMatrix[row][col]; }
inline int GetNRows() const { return nRows; }
inline int GetNCols() const { return nCols; }
private:
int nRows, nCols;
T ** pMatrix;
};
This is the bug:
for (int i = 0; i < nCols; i++) {
pMatrix[i] = new T[nCols];
}
The loop should be until nRows, not nCols.
Other than that, let me tell you about something I did when I got tired of allocating 2-d arrays. I had to do a 3-d array. I used a map, that mapped from a coordinate - a struct holding x, y, z to the type I wanted.
I worked fast, and no need to allocate or deallocate. Assigning to a coordinate was simply done by
mymap[Coord(x, y, z)] = whatever...
Of course I needed to define the Coord struct and overload the < operator, but I found that way more comvenient than trying to allocate and deallocate a 3-d array.
Of course you will need to check if this scheme is fast enough for you. I used it to draw cells within a big cube using OpenGL and had no complaints at all.
Concerning the bug, #CodeChords_man explained it right. I have notes on implementation. I recommend to look through this wonderful FAQ post.
You should not use dynamic memory allocation unless you are 100% sure that
You really need it
You know how to implement it
I don't know of the first, and how the performance is crucial for you. But as for the second, you at least violated the rule of three. You class is very unsafe to use. If you copy it, the memory buffer will then be double-deleted.
You should not afraid to used STL containers, they are fast and optimized. At least the std::vector, it is as fast as the raw pointer in many scenarios. You can rewrite you class using std::vector as follows:
template <typename T>
class Matrix {
public:
typedef std::vector<T> MatrixRow;
typedef std::vector<MatrixRow> MatrixBody;
Matrix(int m, int n) : nRows(m), nCols(n), _body(m, MatrixRow(n)) {}
const MatrixBody& GetMatrix() const { return _body; }
const MatrixRow& GetRow(int i) const { return _body[i]; }
inline T Cell(int row, int col) const { return _body[row][col]; }
inline int GetNRows() const { return nRows; }
inline int GetNCols() const { return nCols; }
private:
int nRows, nCols;
MatrixBody _body;
};
Since this class is not using dynamic memory allocation, it is safe to copy and assign. You also don't need to explicitly store nRows and nCols in this case; you can use _body.size() and _body[0].size() instead.
Concerning underlying vector of vectors, it is dereferenced using the same [i][j] construction. It is easily iterated with begin() and end(). And if you absolutely need to use the raw pointer in some routine, you can always access it with &row[0].
The only possible difficulty is that you cannot easily convert MatrixBody to T**. But think it twice, maybe you don't really need to use T** at all.

C++ Matrix Class

In C, if I wanted to create a matrix struct, I would use:
struct matrix {
int col, row;
double data[1]; // I want the matrix entries stored
// right after this struct
}
Then I can allocate it with
matrix* allocate_matrix(int row, int col) {
matrix* m = malloc(sizeof(matrix) + sizeof(double) * (row * col - 1));
m->row = row; m->col = col;
return m;
}
Now do I do the equiv in C++?
EDIT:
I want to know the cannonical way to implement a matrix class in C++.
nota bene.
This answer has 20 upvotes now, but it is not intended as an endorsement of std::valarray.
In my experience, time is better spent installing and learning to use a full-fledged math library such as Eigen. Valarray has fewer features than the competition, but it isn't more efficient or particularly easier to use.
If you only need a little bit of linear algebra, and you are dead-set against adding anything to your toolchain, then maybe valarray would fit. But, being stuck unable to express the mathematically correct solution to your problem is a very bad position to be in. Math is relentless and unforgiving. Use the right tool for the job.
The standard library provides std::valarray<double>. std::vector<>, suggested by a few others here, is intended as a general-purpose container for objects. valarray, lesser known because it is more specialized (not using "specialized" as the C++ term), has several advantages:
It does not allocate extra space. A vector rounds up to the nearest power of two when allocating, so you can resize it without reallocating every time. (You can still resize a valarray; it's just still as expensive as realloc().)
You may slice it to access rows and columns easily.
Arithmetic operators work as you would expect.
Of course, the advantage over using C is that you don't need to manage memory. The dimensions can reside on the stack, or in a slice object.
std::valarray<double> matrix( row * col ); // no more, no less, than a matrix
matrix[ std::slice( 2, col, row ) ] = pi; // set third column to pi
matrix[ std::slice( 3*row, row, 1 ) ] = e; // set fourth row to e
C++ is mostly a superset of C. You can continue doing what you were doing.
That said, in C++, what you ought to do is to define a proper Matrix class that manages its own memory. It could, for example be backed by an internal std::vector, and you could override operator[] or operator() to index into the vector appropriately (for example, see: How do I create a subscript operator for a Matrix class? from the C++ FAQ).
To get you started:
class Matrix
{
public:
Matrix(size_t rows, size_t cols);
double& operator()(size_t i, size_t j);
double operator()(size_t i, size_t j) const;
private:
size_t mRows;
size_t mCols;
std::vector<double> mData;
};
Matrix::Matrix(size_t rows, size_t cols)
: mRows(rows),
mCols(cols),
mData(rows * cols)
{
}
double& Matrix::operator()(size_t i, size_t j)
{
return mData[i * mCols + j];
}
double Matrix::operator()(size_t i, size_t j) const
{
return mData[i * mCols + j];
}
(Note that the above doesn't do any bounds-checking, and I leave it as an exercise to template it so that it works for things other than double.)
You could do it that way. The only difference is you'd need to cast the result from malloc.
Rather, you would use a vector, either as a 1D array with computed indexing or an embedded vector. (The former matches your code better.)
For example:
template <typename T> // often, they are templates
struct matrix
{
// should probably be hidden away, and the class would
// provide `at` and `operator()` for access
int col, row;
std::vector<T> data;
matrix(int columns, int rows) :
col(columns), row(rows),
data(col * row)
{}
}
matrix m(4, 4);
m.data[1 + 1 * 4] = /* ... */;
Or:
template <typename T>
struct matrix
{
int col, row;
std::vector<std::vector<T> > data;
matrix(int columns, int rows) :
col(columns), row(rows),
data(col, std::vector(row))
{}
}
matrix m(4, 4);
m.data[1][1] = /* ... */;
But these are only examples. You'd want to make a full-fledged class; if you want more advice on that, edit your question and clarify you'd like to know the canonical way of implementing matrix classes.
There are pre-existing matrix classes. My favorite is that from boost, UBLAS.
There's lots of subtleties in setting up an efficient and high quality matrix class. Thankfully there's several good implementations floating about.
Think hard about whether you want a fixed size matrix class or a variable sized one.
i.e. can you do this:
// These tend to be fast and allocated on the stack.
matrix<3,3> M;
or do you need to be able to do this
// These tend to be slower but more flexible and partially allocated on the heap
matrix M(3,3);
There's good libraries that support either style, and some that support both.
They have different allocation patterns and different performances.
If you want to code it yourself, then the template version requires some knowledge of templates (duh). And the dynamic one needs some hacks to get around lots of small allocations if used inside tight loops.
You could use a template like :
#include <iostream>
using std::cerr;
using std::endl;
//qt4type
typedef unsigned int quint32;
template <typename T>
void deletep(T &) {}
template <typename T>
void deletep(T* & ptr) {
delete ptr;
ptr = 0;
}
template<typename T>
class Matrix {
public:
typedef T value_type;
Matrix() : _cols(0), _rows(0), _data(new T[0]), auto_delete(true) {};
Matrix(quint32 rows, quint32 cols, bool auto_del = true);
bool exists(quint32 row, quint32 col) const;
T & operator()(quint32 row, quint32 col);
T operator()(quint32 row, quint32 col) const;
virtual ~Matrix();
int size() const { return _rows * _cols; }
int rows() const { return _rows; }
int cols() const { return _cols; }
private:
Matrix(const Matrix &);
quint32 _rows, _cols;
mutable T * _data;
const bool auto_delete;
};
template<typename T>
Matrix<T>::Matrix(quint32 rows, quint32 cols, bool auto_del) : _rows(rows), _cols(cols), auto_delete(auto_del) {
_data = new T[rows * cols];
}
template<typename T>
inline T & Matrix<T>::operator()(quint32 row, quint32 col) {
return _data[_cols * row + col];
}
template<typename T>
inline T Matrix<T>::operator()(quint32 row, quint32 col) const {
return _data[_cols * row + col];
}
template<typename T>
bool Matrix<T>::exists(quint32 row, quint32 col) const {
return (row < _rows && col < _cols);
}
template<typename T>
Matrix<T>::~Matrix() {
if(auto_delete){
for(int i = 0, c = size(); i < c; ++i){
//will do nothing if T isn't a pointer
deletep(_data[i]);
}
}
delete [] _data;
}
int main() {
Matrix< int > m(10,10);
quint32 i = 0;
for(int x = 0; x < 10; ++x) {
for(int y = 0; y < 10; ++y, ++i) {
m(x, y) = i;
}
}
for(int x = 0; x < 10; ++x) {
for(int y = 0; y < 10; ++y) {
cerr << "#(" << x << ", " << y << ") : " << m(x,y) << endl;
}
}
}
*edit, fixed a typo.
you could do it with a template, if the matrix size is known at compile-time :
template <int width, int height>
class Matrix{
double data[height][width];
//...member functions
};
For a matrix class, you want to stay away from overloading the [] operator.
See C++ FAQ 13.10
Also, search the web for some freeware Matrix classes. Worst case, they can give you guidance. Best case, less software that you have to write and debug.
There is no "canonical" way to do the matrix in C++, STL does not provide classes like "matrix". However there are some 3rd party libraries that do. You are encouraged to use them or write your own implementation. You can try my implementation derived from some public implementation found on the internet.
The library called, Matrix supports so many features including mathematics operations, dumping and logging features, associative containers, multiple dimensions and etc.
Usage
its usage is similar to c++ arrays.
Matrix<int> A(1, 2);
Matrix<int> B(2, 3);
Matrix<int> result(1, 3);
A[0][0] = 7;
A[0][1] = 10;
B[0][0] = 1;
B[0][1] = 4;
B[0][2] = 2;
B[1][0] = 1;
B[1][1] = 2;
B[1][2] = 100;
result = A * B;
result.dump.matrix();
Result:
Matrix view:
- -
| 17 48 1014 |
- -
Here is the documentation and Github page.
In C++ you can use like this:
matrix *p = new matrix;
After that,
delete p;