template <class T>
class Matrix
{
private:
T** data; // matrix elements stored here
int rows; // number of rows
int cols; // number of columns
public:
Matrix(int numRows = 0, int numCols = 0); // makes storage allocation but leaves it uninitialized, for 0,0 dont allocate memory
Matrix(T const* const* inputData, int numRows, int numCols);
Matrix(const Matrix& rhs);
~Matrix();
I have to do implementation and normally I can. But this time I can't figure out what to do with T**
I am pretty newbie as you can see. At the first i thought as a double pointer but clearly it isn't. I can only use the ”iostream” header file and the Matrix class’ interface header file that which is given to me.
Look in the following link, its pretty self-explanatory, and will guide your implementation (supposing you know how to do it without templates):
http://www.cplusplus.com/doc/tutorial/templates/#class_templates
You will end initializing your class as:
Matrix<int> *myMatrix = new Matrix<int>(data, 10,10);
or
Matrix<int> myMatrix(10,10);
Matrix::Matrix(int numRows = 0, int numCols = 0)
:data(new T[numRows][numCols]){}
Matrix::~Matrix(){delete [] data;}
I'd let yourself figure out the rest.
Related
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];
In visual studio _CrtDumpMemoryLeaks() has detected memory leaks! But I could not find how it is happening. Please tell me what is wrong with the following code.?
// Declaration
template <class T> class cMatrix {
private:
std::vector<std::vector<T> > mat;
unsigned rows;
unsigned cols;
public:
cMatrix(unsigned _rows, unsigned _cols, const T& _initial);
cMatrix(const cMatrix<T>& rhs);
virtual ~cMatrix();
}
//Constructor
template<class T>
cMatrix<T>::cMatrix(unsigned _rows, unsigned _cols, const T& _initial) {
mat.resize(_rows);
for (unsigned i=0; i<mat.size(); i++) {
mat[i].resize(_cols, _initial);
}
rows = _rows;
cols = _cols;
}
//VirtualDestructor
template<class T>
cMatrix<T>::~cMatrix() {}
mat1 and mat4 can be destroyed after CrtDumpMemoryLeaks() call, move declaration of variable to own block.
int main()
{
{
cMatrix<double> mat1(2, 3, 23.0), mat4(2, 3, 15.0);
}
CrtDumpMemoryLeaks();
return 0;
}
Problem is that _CrtDumpMemoryLeaks(); is called in the same scope as vector is, so object does not get destroyed when it is called.
This won't show any memory leaks:
int main()
{
{
cMatrix<double> mat1(2, 3, 23.0), mat4(2, 3, 15.0);
}
_CrtDumpMemoryLeaks();
}
By the way, more efficient way to define cMatrix would be
// Declaration
template <class T> class cMatrix {
private:
std::vector<std::vector<T> > mat;
unsigned rows;
unsigned cols;
public:
cMatrix(unsigned _rows, unsigned _cols, const T& _initial);
virtual ~cMatrix();
};
//Constructor
template<class T>
cMatrix<T>::cMatrix(unsigned _rows, unsigned _cols, const T& _initial)
: mat(_rows,std::vector<T>(_cols,_initial))
, rows(_rows)
, cols(_cols)
{
}
//VirtualDestructor
template<class T>
cMatrix<T>::~cMatrix() {}
You've gotten some advice giving one possible way to deal with the problem you've seen. At least IMO, there's a somewhat better way though. Instead of mixing the diagnostic code with the other code, then adding braces to introduce a scope that's irrelevant to the real code, I'd separate the leak-dumping code even more completely, by putting it into a separate class:
struct leak_dumper {
~leak_dumper() { _CrtDumpMemoryLeaks(); }
} dump_leaks_at_exit;
This creates a global instance of the object, so you can simply add these three lines of code to the same file that contains your main (or WinMain) and it'll do the leak-dumping after main exits (with no other modification of your existing code).
As far as how to define a 2D matrix goes: a vector of vectors generally makes sense only if different rows of the matrix might contain different numbers of columns. If you want a rectangular matrix, you're generally better off with a single vector, and converting 2D coordinates to one dimension in an overloaded operator.
template <class T>
class matrix2D {
std::vector<T> data;
int columns;
public:
T &operator()(int x, int y) {
return data[y * columns + x];
}
matrix2D(int x, int y) : data(x*y), columns(x) {}
};
This reduces the total memory you use and, perhaps more importantly, keeps the data contiguous instead of allocating the data for each row separately.
I'm trying to perform a strided access to a submatrix with a single index. I need this for a library I'm working on which uses expression templates. I have worked out the following class, where the access is performed by the overloaded operator[], see below:
template <class A, class Type>
class SubMatrixExpr
{
private:
int Rows_; // Rows of the SubMatrix
int Columns_; // Columns of the SubMatrix
int Rows_up_; // Rows of the original Matrix
int Columns_up_; // Columns of the original Matrix
int a_, c_; // Starting indices of the SubMatrix as evaluated in the original Matrix
int rowstep_, columnstep_; // Stride along rows and columns for the original matrix
A M_;
public:
SubMatrixExpr(A &M, int Rows_up, int Columns_up, int Rows, int Columns, int a, int rowstep, int c, int columnstep) :
a_(a), c_(c), M_(M),
Rows_(Rows),
Columns_(Columns),
Rows_up_(Rows_up), Columns_up_(Columns_up),
rowstep_(rowstep), columnstep_(columnstep) { }
inline const Type& operator[](const int i) const
{
const int LocalRow = i/Columns_;
const int LocalColumn = i%Columns_;
const int GlobalRow = a_+rowstep_*LocalRow;
const int GlobalColumn = c_+columnstep_*LocalColumn;
return M_[IDX2R(GlobalRow,GlobalColumn,Columns_up_)];
}
inline Type& operator[](const int i)
{
// Similar to above
}
};
where
#define IDX2R(i,j,N) (((i)*(N))+(j))
The overloaded operator[] works correctly, but is computationally very expensive.
Is there any way to better implement the overloaded operator[]?
Thanks a lot in advance.
The only way you may got speedup is if you now the size of the matrices and sub-matrices at compile time. Then using template / constexpr may speedup things. For example if the size is known to be a power of 2 at compile time, the compiler will be able to replace division by shift.
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.
I need a Matrix class for a project I'm doing in C++ but I don't know how to declare the constructor.
I know I need a height and a width. But how do I go about the part where I store the values? What's the best practice?
I thought about having my constructor be:
Matrix::Matrix(int height, int width, int[] values)
and so the private attributes of my class would be height, width and? How can I say that I want to store a number of values that I don't have yet?
I hope this makes sense... I'm finding it very hard to explain and that's probably because I'm very confuse. I'm very new with C++, so any extra help will be appreciated.
Just for an illustration list of constructors for OpenCV's cv::Mat class:
// constructors
Mat();
// constructs matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
Mat(int _rows, int _cols, int _type);
Mat(Size _size, int _type);
// constucts matrix and fills it with the specified value _s.
Mat(int _rows, int _cols, int _type, const Scalar& _s);
Mat(Size _size, int _type, const Scalar& _s);
// copy constructor
Mat(const Mat& m);
// constructor for matrix headers pointing to user-allocated data
Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP);
Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP);
// creates a matrix header for a part of the bigger matrix
Mat(const Mat& m, const Range& rowRange, const Range& colRange);
Mat(const Mat& m, const Rect& roi);
// converts old-style CvMat to the new matrix; the data is not copied by default
Mat(const CvMat* m, bool copyData=false);
// converts old-style IplImage to the new matrix; the data is not copied by default
Mat(const IplImage* img, bool copyData=false);
// builds matrix from std::vector with or without copying the data
template<typename _Tp> explicit Mat(const vector<_Tp>& vec, bool copyData=false);
// helper constructor to compile matrix expressions
Mat(const MatExpr_Base& expr);
// assignment operators
Mat& operator = (const Mat& m);
Mat& operator = (const MatExpr_Base& expr);
I think this is good place to get inspiration or use it for your project, hover I'd recommend following constructors:
// Will declare whether to fill allocated data with zeros, ones or leave it be
enum MatrixFill { NO_INITIALIZATION, ZERO_FILL, ONES_FILL};
Matrix( const int width, const int height, const MatrixFill fill = NO_INITIALIZATION);
// To initialize from T data[] = {1,2,3,1,2,3,1,2,3};
Matrix( const int width, const int height, const T *data);
// To initialize from T data[][3] = {{1,2,3},{1,2,3},{1,2,3}};
Matrix( const int width, const int height, const T **data);
// To initialize from other matrix
Matrix( const Matrix &orig);
// Don't forget assign operator
Matrix &operator=(const Matrix &orig);
I'd also create type SubMatrix which wouldn't contain any data just link to parent data and range which would allow you to do this:
Matrix my( old.getSubMatrix( row, col, rowsCount, colsCount));
// And of course it'd have constructor like this:
Matrix( const SubMatrix &orig);
You may add many more constructors but I'd start with those five. Ask questions if you have any.
I'd learn from the pros: http://www.boost.org/doc/libs/1_48_0/libs/numeric/ublas/doc/matrix.htm#matrix
You should probably have a number of constructors, based on how you expect to use the class.
Assuming you plan to use Matrix for some kind of linear algebra, you should have a constructor which initializes the elements to zero:
Matrix(int height, int width); // initializes elements to 0
You should have constructors that initialize the elements from whatever data source you expect to find convenient (below, the type T is the element type of your Matrix):
Matrix(int height, int width, const std::vector<T> &data); // init from vector
Matrix(int height, int width, const T *data); // init from array
If you want to be able to declare an array of matrices, you need a default constructor:
Matrix(); // uninitialized or default array (to be initialized later)
You should also either define or disable copy constructors and assignment operators (or C++ will define them for you, badly):
Matrix(const Matrix &orig); // copy constructor
Matrix& operator=(const Matrix &orig); // assignment operator
I would really try to look for a book about OO design and their application in C++. As this question (besides hard to understand) shows a general misunderstanding of how object oriented languages work. I could explain it here in this topic; but that would be redundant and book authors can do it much better than me.
Basically what I understood from this question is that you know the sizes of your matrix, yet don't know the values they will get when you create them?
In that case simply make a constructor with only the sizes. And initialize the matrix to some "NULL" value. (Possibly even set a private member to false, indicating it isn't completely usable yet). The class and constructor would look like:
class Matrix() {
public:
Matrix(int nRows, int nColumns);
private:
int numRows;
int numColums;
std::vector<VALUE_TYPE> val;
};
Matrix::Matrix(int nRows, int nColums) {
int numRows = nRows;
int numColumns = nColums;
std::vector<VALUE_TYPE> val(nRows * nColums);
}
Simply said: the constructor only makes sure the memory is "allocated". Then you use other functions to fill in the actual values.
If you wish to provide "something", where you don't know exactly what "something" is. But you do know it is a container of data - you should use standard iterators (or templates). This is the manner how c++ handles inserting of data to standard containers. The function would be like this:
template <typename InIt>
Matrix::Matrix(int nRows, int nColums, InIt begin, InIt end) {
int numRows = nRows;
int numColumns = nColums;
//[begin, end) now holds the data - manipulate it at will.
std::vector<VALUE_TYPE> val(begin, end);
val.resize(nColums * nRows);
}
But once again: I'd take a book as the question to me seems unclear and answered by books.
Not strictly related to cpstructors but ... are you matrix expected to be resized during their life? If not, consider the idea not to have numRows and numCols as "variables" (they will never vary) but as template parameters.
Your matrix can be so declared as
Matrix<int,3,3> a; //a 3x3 integers
Matrix<double,3,2> a; //a 3x2 doubles
This will let impossible operations (like adding matrix with different sizes) impossible to compile.