Dynamic Memory Allocation Matrix - c++

What is the best option to allocate memory for Matrix?
I need to allocate memory in the first Mat Constructor .
The second Mat Constructor needs 1 argument, when Matrix is considered 1D array, so the number of rows will be 1. I also have to allocate memory in this second constructor.
Matrix data should be double
this is what I have tried:
#include<iostream>
class Mat{
uint16_t rows;
uint16_t colls;
double *mData; // the 2D array// matrix
Mat(uint16_t r, uint16_t c){ // constructor with 2 parameters -
// alocating memory for matrix
this-> rows = r;
this-> colls = c;
this-> mData = new double [rows][colls];
}
Mat(uint16_t x){ //constructor with 1 parameter // alocating memory
//for the case when number of rows = 1 , so the matrix becomes 1D array[]
this-> rows = x;
this-> mData = new double [rows];
}
};
I'm not good at pointers, so i can't figure out what I am missing.
"Array size is not a constant expression"
--UPDATE --
Full request:
Create the Mat class by implementing its contents as follows:
The class must contain 2 private attributes called mCols andmRows.These are the dimensions of the matrix, and their type is a 16-bit integer without a 16-bit mark.
The class must contain 1 private attribute named mData. This is a pointer to fractional numbers on double precision, and the memory for this pointer will be allocated in the constructor.
A constructor that takes as an argument two unmarked integers that represent the number of lines and the number of columns of an array and allocates memory to store these values.
A second constructor to take as an argument a single number. In this case, the array is considered a vector, the number of lines will be by default 1 and the received argument represents the number of columns. Of course, the allocation of memory to be able to store numbers must also be done in this case.
A third constructor who doesn't take any arguments. It will only initialize the integer attributes with the value of 0.
A fourth constructor, which will be the copy constructor. It receives as an argument an object of type const Mat & and its role is to copy all the values of the attributes of the given object as a parameter in the current object (this).
New code:
class Mat{
private:
uint16_t mRows;
uint16_t mCols;
double *mData;
public:
Mat(uint16_t r, uint16_t c){
mRows = r;
mCols = c;
mData = new double[mRows * mCols];
}
Mat(uint16_t c){
mCols = c;
mRows = 1;
mData = new double [1 * mCols];
}
Mat(){
mRows = 0;
mCols = 0;
}
Mat(const Mat &mat) : mRows(mat.mRows), mCols(mat.mCols), mData(mat.mData){
}
};

First of all, you need to use double** instead of double* for implementing 2d array
Secondly, I guess you need public constructors(now you have private)
And of course is better to use std::vector, but if you don`t want to, you can use my suggested code:
Mat(uint16_t r, uint16_t c){ // constructor with 2 parameters -
// alocating memory for matrix
this-> rows = r;
this-> colls = c;
this->mData = new double*[rows];
for(int i = 0; i < rows; i++) {
mData[i] = new double[colls];
}
}

Related

Why do I have to free 2D array twice to avoid memory leak?

I am running into a memory leak problem when allocating a 2D array.
But I could not understand why the memory leaks.
My reasoning is that at Note A, I have already freed allocated memory, since data_[0] == data_, why do I have to do the free at Note B?
class Matrix {
public:
Matrix(int r, int c) {
this->rows = r;
this->cols = c;
data_ = new int*[r];
for (int i = 0; i < r; i++) {
data_[i] = new int[c];
}
}
~Matrix() {
for (int i = 0; i < this->rows; i++) {
delete [] data_[i]; // Note A;
}
delete[] data_; // Note B; <-- not doing this line will leak memory, but why?
}
private:
int rows;
int cols;
int **data_;
};
What you post there isn't really a 2D array, it's a 1D array-of-pointers (data_), and then you allocate a separate array-of-ints for each element of the first array (so data_[0] is an array of c ints, data_[1] is an array of c ints, and so on).
Given that, it's natural that you'll have to do one delete[] in your destructor for each new that you performed earlier in your constructor.
A graphical diagram of your memory allocations and how they point to each other might look like this (if c==6 and you have set all of your arrays' integers to 0):
A real 2D array allocation would look like this: int * array2D = new int[6][8];, but of course C++ only supports 2D arrays if the array-dimenions are compile-time constants, so that probably wouldn't solve the problem your Matrix class is meant to solve.
When you have created 2D array (for example 3x3), you have created 1 array with 3 elements, where each element is pointer to separate array. So to clear memory for this matrix you need to clear 4 arrays (3 rows and 1 array containing pointers).
You can check how many times in your code you are calling new operator
it will be r+1 times
data_ = new int*[r];// 1 time
for (int i = 0; i < r; i++ {
data_[i] = new T[c]; // r times
}
Part I:
The line data_ = new int*[r]; allocates and default initializes a dynamic array of int* through new, so you would need to provide a corresponding delete [] data_; for this line.
Part II:
The line data_[i] = new int[c]; dynamically allocates and default initializes an int array and then the pointer to that first element is returned and stored as the data_[i] element. So here again you would need a corresponding delete [] data_[i]; to get rid of the memory leak.
So these were the reasons why you need two separate delete []. The process is as shown in the screenshot. Also note that the important thing is the default initialization. So the int array elements will not all have a value 0 as wrongly shown in the answer by #Jeremy Friesner.

Constructing an array of class attribute in a different class C++

I have to do a project where one class Row has an array of integers int* OneArray and then another class Array has an array of the first class Row* TwoDArray. In essence the class has a 2D array on integers, and I can easily do the construction of the 2D array when it is in one class. However, now I am completely stumped.
The construction of the Row is simple enough:
//set length of array
numOfRows = intRows;
//Create space for array
OneArray = new int[intRows];
//populate array with random numbers
for(int i=0; i<intRows; i++)
{
OneArray[i] = GenerateRandom(9,0);
}
This is where I am stuck (Construction of Array):
//Set Number of Cols
NumOfCol = intCols;
//create length for each row
int intLength = 4;
for(int i=0; i<NumOfCol; i++)
{
//create space and call row constructor with length
TwoDArray = new Row(intLength);
//increase length for jagged array
intLength++;
}
As it is now it writes over the current array after each for loop (which is expected). So, I need to index TwoDArray like TwoDArray[i], but as soon as I try to do that then I get this error:
"invalid user-defined conversion from 'Row*' to 'const Row&'."
Note: If I take the line out of the for loop only the first array is made and not until intCol. intLength is increasing because I technically need a jagged array which has got different sizes in each array.
My classes look like this:
class Row
{
public:
//Constructors
Row();
Row(int intRows);
Row(const Row& objPrev);
//Accessors
int getNumOfRows();
int getRowArray(int intRow);
//Mutators
void setRowArray(int intRow, int intChange);
//Destructor
~Row();
private:
int* OneArray;
int numOfRows;
}
and
class Array
{
public:
//Constructors
Array();
Array(int intRows, int intCols);
Array(const Array& objPrev);
//Accessors
int getNumOfCol();
Row getTwoDArray(int intCol, int intRow);
//Mutators
void setTwoDArray(int intCol, int intRow, int intChageTo);
//Destructor
~Array();
private:
Row* TwoDArray;
int NumOfCol;
}
Any Help or suggestions are appreciated.
With your loop in Array you allocate a single Row object multiple times, overwriting the pointer in each loop. That leads to a memory leak as only the last will be available through the variable TwoDArray. Also, at the end of the loop all you will have is an "array" of only a single element, the last allocated Row object.
The problem is that you can't do the array allocation using new[] at the same time as you call a specific constructor. You can not do e.g.
TwoDArray = new Row[NumOfCol](intLength);
Instead you have to split the allocation and initialization into two parts:
TwoDArray = new Row[NumOfCol]; // Allocates memory, default constructed Row objects
for (int i = 0; i < NumOfCol; ++i)
{
TwoDArray[i] = Row(intLength); // Initialize each element
}
This of course requires you follow the rules of three or five (or zero) for the copying in the loop to work.

C++ Set 2d array sizes of class member array in constructor

I only found solutions for 1d arrays, but couldn't apply them to 2d arrays.
The possible solutions included "vectors", "templates", and "pointers to arrays".
I know I can get vectors to work, but I would rather use either of the other 2. Preferably templates because I don't want to manually destruct, but pointers work too. (the pointer would be pointed to an array created in the constructor).
The class contains an empty 2d array called screen. The constructor is supposed to set its size. I tried too many things for me to list them all here, but I'll show what I currently have. (last thing i tried were pointers to arrays created in the constructor. in this case screen was a char pointer)
Screen::Screen(const int w, const int h) : screen(new char[h][w]) {} {
width = w;
height = h;
}
array size in new-expression must be constant
I failed implementing either of those strategies and received many kinds of errors while trying to make it work. How would I solve this problem? (primarily I want to know how to do this with templates. if not possible then with pointers to arrays created in the constructor)
The question was a little ambiguous, but it sounds like you want to dynamically allocate an array given some input.
Edit I changed the answer to match the code you provided. This creates a 2d array of chars given the height and width.
class Screen {
private:
char **data;
int rows;
int columns;
public:
Screen(int num_rows, int num_cols);
};
Screen::Screen(int num_rows, int num_cols) {
data = new char * [num_rows];
for (int i = 0; i < num_rows; ++i) {
data[i] = new char[num_cols];
}
rows = num_rows;
columns = num_cols;
}
This creates an empty 2D array of chars.
Explanation: All arrays in c are just pointers to the first block in memory of the type you have declared. By having the member variable as double pointer, you have an array of char pointers, which each point to the first value in each of their respective arrays.
BUT be careful, you WILL need to free the data variable to avoid memory leaks, by declaring a destructor.
Screen::~Screen() {
for (int i = 0; i < rows; ++i) {
delete[] data[i];
}
delete[] data;
}

want to declare arrays by using constructor with variables

class matrix
{
public:
matrix();
matrix(int row, int column);
~matrix();
private:
const int DEFAULT_SIZE;
int size_row, size_column;
double *entry;
};
// main function
int
main()
{
//make a matrix of default size
matrix A; /* no error */
delete A;
//make 5 matrices of default size
matrix *B = new matrix [5]; /* no error */
delete [] B;
//make a matrix of size 15x15
matrix C(15, 15); /* no error */
delete C;
//make 5 matrices of size 15x15
matrix *D = new matrix(15, 15) [5]; /* compile error !! */
return 0;
}
//Define functions
matrix::matrix() : DEFAULT_SIZE(10)
{
size_row = DEFAULT_SIZE;
size_column = DEFAULT_SIZE;
entry = new double [size_row*size_column];
}
matrix::matrix(int row, int column) : DEFAULT_SIZE(10)
{
size_row = row;
size_column = column;
entry = new double [size_row*size_column];
}
matrix::~matrix()
{
delete [] entry;
}
I'm studying about constructor.
I'd like to declare arrays by using constructor with variables.
Can you correct my code line?
Please see the line below '//make 5 matrices of size 15x15'
Also, in this case, how can I use destructor?
To make an array of 5 elements that each get constructed with (15,15), you could do the following in C++11:
matrix* D = new matrix[5]{
{15,15}, {15,15}, {15,15}, {15,15}, {15,15}
};
But it would be much simpler to just use a vector:
std::vector<matrix> D(5, {15,15}); // C++11
std::vector<matrix> D(5, matrix(15,15)); // pre-C++11
After looking at your source code here is what I have seen! In your class for your private members your row and column sizes should not be of type int, they should be unsigned int. The reason they should be unsigned int is because an int without an unsigned is a signed value by default which means it can have negative numbers. For the amount of rows and columns in a matrix that does not make sense. With an unsigned int value it ranges from [0, max_value] of an unsigned int. Another thing to take care in is what if someone entered in 0 for either the row or column size or both? Then you would still not have a valid matrix. A little logic needs to be done here; if someone enters in a 0 for either then you have to make a decision as what the default behavior should be. Do you want to use the default value of 10? Also a value of 1x1 does not make sense either! Now you could have 1x4 or 4x1 then these would not be exactly a Matrix but they would be vectors that are either row or column major in order. In my honest opinion your default matrix size from the base constructor without any arguments should be 2x2. If a user specifies 1 for either parameter then the other parameter should be greater then 1. Also there is no need for 2 constructors here, this is duplicate code and can be done with just 1 constructor. Also there is no need to call your destructor, this gets automatically called when this class object goes out of scope.
For matrices would you think that the elements should be public for easy access?
Right now as it stands your (element) array is private meaning no outside class can access them, now if this is the behavior you want then you will need functions to access them and to set them if the values need to change.
Based on your class implementation here is what I did to show you the changes I have mentioned above.
#include <vector>
#include <array>
class Matrix {
private:
const unsigned int DEFAULT_SIZE;
unsigned int size_row, size_column;
double* elements;
public:
explicit Matrix( unsigned int row = 0; unsigned int column = 0 );
~Matrix();
// Copy Constructor
Matrix( const Matrix& c );
// Operator = Needed
Matrix& operator=( const Matrix& c );
}; // Matrix
Matrix::Matrix( unsigned int row, unsigned int column ) : DEFAULT_SIZE(2) {
// Check if both are 0 Or both are 1 - use default sizes
if ( (row == 0 && column == 0) ||
(row == 1 && column == 1) ) {
row = DEFAULT_SIZE;
column = DEFAULT_SIZE;
}
// Check [Row,Column] For [0,1] && [1,0]
if ( row == 0 && column == 1 ) {
row = 1;
column = DEFAULT_SIZE;
} else if ( row == 1 && column == 0 ) {
row = DEFAULT_SIZE;
column = 1;
}
size_row = row;
size_column = column;
element = new double[size_row * size_column];
} // Matrix
Matrix::~Matrix() {
delete [] elements
} // ~Matrix
Matrix::Matrix( const Matrix& c ) : DEFAULT(2) {
this->size_row = c.size_row;
this->size_column = c.size_column;
this->element = c.element;
} // Matrix(copy)
Matrix& Matrix::operator=( const Matrix& c ) {
// Assignment Can Only Happen If Both Matrices Are Of The Same Dimensions:
// You can not set a 4x3 = 6x9 for this does not make sense
if ( (this->size_row == c.size_row) &&
(this->size_column == c.size_column) ) {
this->element = c.element;
return *this;
} // operator=
As for the code in your main function I see a few errors that need to be fixed. The first two lines:
Matrix A;
delete A;
You are declaring Matrix A; then on the next line you are calling delete on A.
This is your first error: A is an instance of Matrix. This is a local stack variable that belongs to the scope of the main function. There is no need to call delete on this! When your instance of Matrix (A) goes out of scope the Matrix::~Matrix() is called implicitly for you behind the scenes, there is no need to invoke it.
Your next two lines of code:
Matrix* B = new Matrix[5];
delete [] B;
These two are correct and there are no problems here. You instance B is a pointer to a type object Matrix and because new is used here it is created on the heap and because you have [5] B is not just a pointer to this type but is a pointer on the heap to the first address of you dynamically allocated array. Then you call delete with the [] operator on B which is correct.
Your next two lines of code:
Matrix C(15,15);
delete C;
You are declaring an instance of a Matrix object called C on the stack where you are now using your defined constructor. Again on the second line here there is no need to call delete on C.
As for your last 2 lines of code this is not as simple as trying to do want you want but isn't all that trivial. In order for you to create your dynamic array of Matrices that all have a default size of 15x15 needs a little more work. In order to do this properly you can see from the class implementation that I added a Copy Constructor and an overloaded = operator. There are three steps to achieve this.
// First Step - Create A Single Stack Instance With Size [15,15]
Matrix D = Matrix( 15, 15 ); // This Will Be Used Later To Populate Your Array
// Second Step - Create An Array of 5 Matrices On The Heap
Matrix* E = new Matrix[5]; // Right Now All Five Are Using Default Size 2x2.
// Step Three Now We Update Them Using Our operator=()
for ( unsigned int i = 0; i < 5; i++ ) {
E[i] = D;
}
// Then Delete the Array
delete [] E; // Only Need To Delete E
However This WILL NOT WORK: Due to how our operator=() is defined! So how do we achieve this? There are two ways and both work. So You Can Remove Matrix E, the for loop and the delete [] E lines. Leave the Matrix D for that will be needed!
The First is easier: If you noticed I included both vector and array from the STL for this case I will use the vector class since it is the most commonly used.
// We already have: Matrix D = Matrix( 15, 15 );
// You Want an Array of 5
std::vector<Matrix> vMatrices; // This will create a vector of stack Matrices but at first it will be "EMPTY"
for ( unsigned int i = 0; i < 5; i++ ) {
vMatrices.push_back( D );
}
// Now You Have A vector of 5 Matrices.
// If You Want Vector of Pointers
std::vector<Matrix*> vpMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
vpMatrices.push_back( &D );
}
// To clean up your vectors you can simply do
vMatrices.clear();
vpMatrices.clear();
// The Other Way Would Be To Use std::array but it is less commonly used.
// If You know you will only ever need a set amount this works good
std::array<Matrix, 5> aMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
aMatrices.at(i) = D;
}
// For Holding Pointers
std::array<Matrix*, 5> apMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
apMatrices.at(i) = &D;
}
// To Clean Up std::array To Be Honest Not really sure for I do not use them
// But using it here just as an illustration that there are plenty of predefined containers
// to use to hold multiple elements of the same data type.
As a final note about your class, you are creating your size of your matrices and have the elements array defined based on size, however being that everything is private, you have no way to populate it or to access it. Keeping it private means you would have to implement functions to do this and considering the nature of matrices either for them to "Store" data or "Function Calls" or Being a Mathematical Object of Calculations and Operations. You do not want the overhead of accessory functions for this would be a performance hit. There is nothing wrong with keeping the size of the row and columns private, for there is no need to access these outside of the class once they have been defined. But your single dimensional array that is representing your MxN matrix should be publicly defined. Also you should have operator[] defined as well.
If you want to see how a basic math library implements matrices take a look at GLM's math library that is written to work with OpenGL shader language GLSL.
This library is an Headers Only Library. No need to link or include *.dlls or *.libs. All you need to do is store it into a folder on you computer and set you system to have an environment variable that points to its main folder. Then in you IDE if you are using VS all you have to do in the additional include section of the projects properties is use the environment variable defined. This is for using it! But to just look over its contents you can just down load it to any folder and open any of the *.h files. Then you can see how they implemented Matrix classes! You will notice that they are template types and they have predefined types of matrices such as mat2x2, mat2x3, mat2x4, mat3x2, mat3x3, mat3x4, mat4x2, mat4x3, & mat4x4. This is do to the nature of writing Programs and Shaders that are focused on 2D and 3D Graphics so the min required is a 2x2 and the largest that is truly needed is a 4x4. They also have vector classes defined of different sizes, and your matrices can be constructed from different size vectors. But this should serve as a guideline. Here is their link
GLM

Initializing an internally allocated matrix

I have to write a constructor for implementing a function for initializing an internally allocated matrix. The given code looks like (only constructor):
Matrix(const float* m, size_t n) : _n(n), _m(0lu)
{
//Missing
}
So, my first question is: What does the part behind the ':' mean (_n(n), _m(0lu))?
Furthermore, as far as I know, I need a return pointer to the memory I am allocating. Is this correct? My first idea was to use posix_memalign(...). Would this be correct?
Thank you very much!
I am assuming this basic object:
class Matrix
{
// stuff
private:
size_t _n;
float* _m;
}
The part of the constructor is an initialization list. It is synonymous to wiring:
Matrix(const float* m, size_t n)
{
_n = n;
_m = 0lu;
}
Here is a good decription, why you want to use them: [10.6] Should my constructors use "initialization lists" or "assignment"?
But that does not solve your initial problem: "function for initializing an internally allocated matrix"
What the constructor does is copy the size (n) and initialize the pointer to NULL. (NULL is synonymous with 0 [1]) So you need some way to internally allocate and initialize.
I have one problem with the Matrix class. Normally a matrix has 2 dimension, so either it is a NxN matrix or n is the element count and we have no idea what dimension the matrix is. I will assume that it is NxN matrix, since this is quite often used in computer graphics.
Step 1: internally allocated
So, allocate some memory:
_m = new float[n*n];
This can replace the assignment to NULL, since why should it be first set to NULL and then change right after.
Step2: initialized
Assuming that the calling code put sufficient data into m, just use memcpy:
std::memcpy(_m, m, n*n*sizeof(float));
If you feel masochistic, you can also copy the elements each:
for (unsigned int i = 0; i < n*n; i++)
{
_m[i] = m[i];
}
So your final constructor looks like so:
#include <cstring>
Matrix(const float* m, size_t n)
: _n(n), _m(new float[n*n])
{
std::memcpy(_m, m, n*n*sizeof(float));
}
Finally, since you allocated memory you should not forget to delete it in the destructor:
Matrix::~Matrix()
{
delete [] _m;
}
Note the array deleting operator.
[1] In C++11 and C99 this is not fully true under certain circumstances, but these are details and irrelevant.
:_n(n), _m(0lu)
is member internalizer list. Means _n(which seems to be member variable) is assing n to it and simialr for _m
More details here