How to delete and reassign a dynamically allocated pointer - c++

I'm taking a c++ programming course (we are still mostly using C) and we just got to dynamic allocation of memory. For one of my homeworks, I'm asked to create a function that transposes any given matrix. This function is given the following arguments as inputs: a pointer, in which are saved the matrix elements, the number of rows and of colunms. I would like this to be a void type function that changes the order of the stored elements without returning any new pointer.
I tried creating a new pointer, in which I save the elemtens in the correct order (using 2 for loops). Then what I would like to do is deallocating the original pointer (using the delete command), assinging it to the new pointer and finally deleting the new pointer.
This unfortunately does not work (some elements turn out to be random numbers), but I don't understand why.
I hope my code is more precise and clear than my explanation:
void Traspose(float *matrix, const int rows, const int cols ){
auto *tras = new float [rows * cols];
int k = 0;
for(int i = 0; i < cols; i++){
for(int j = 0; j < rows * cols; j += cols){
tras[k] = matrix[j + i];
k++;
}
}
delete[] matrix;
matrix = tras;
delete[] tras;
}

All those lines are wrong:
delete[] matrix;
matrix = tras;
delete[] tras;
You didn't allocate matrix so you don't want do delete it.
You assign tras to matrix and then you delete tras, after that, tras points nowhere, nor does matrix.
matrix = tras is pointless anyway, because matrix is a local variable, and any changes to local variables are lost after the function ends.

You're inventing a problem where none should exist.
A matrix AxB in dimension will transpose to a matrix BxA in size. While the dimensional difference is obvious the storage requirements might not be so. Your storage is identical.
Per the function signature, the change must be done in the same memory allocated to matrix. E.g., the results should be stored back into matrix memory. So, don't delete that memory; leave it alone. It is both large enough to hold the transposition, and owned by the caller regardless.
Rather, do this:
void Traspose(float *matrix, const int rows, const int cols)
{
float *tras = new float[ rows * cols ];
int k = 0;
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows * cols; j += cols)
tras[k++] = matrix[j + i];
}
for (int i=0; i<k; ++i)
matrix[i] = tras[i];
delete [] tras;
}
Note this gets quite a bit simpler (and safer) if the option to use the standard library algorithms and containers is on the table:
void Traspose(float *matrix, const int rows, const int cols)
{
std::vector<float> tras;
tras.reserve(rows*cols);
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows * cols; j += cols)
tras.emplace_back(matrix[j + i]);
}
std::copy(tras.begin(), tras.end(), matrix);
}
Finally, probably worth investigating in your spare time, there are algorithms to do this, even for non-square matrices, in place without temporary storage using permutation chains. I'll leave researching those as an exercise to the OP.

Related

Way to ensure a dynamically allocated matrix is square?

I would like to determine if there is a way to determine whether a dynamically allocated matrix is square (nxn).
The first thing that came to mind was to see if there is a way to find out whether a pointer is about to point to an invalid memory location. But according to these posts:
C++ Is it possible to determine whether a pointer points to a valid object?
Testing pointers for validity (C/C++)
This cannot be done.
The next idea I came up with was to somehow use the sizeof() function to find a pattern with square matrices, but using sizeof() on a pointer will always yield the same value.
I start off by creating a dynamically allocated array to be of size nxn:
int **array = new int*[n]
for(int i = 0; i < n; i++)
array[i] = new int[n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
array[i][j] = 0;
}
}
Now I have a populated square matrix of size nxn. Let's say I'm implementing a function to print a square 2D array, but a user has inadvertently created and passed a 2D array of size mxn into my function (accomplished by the code above, except there are more row pointers than elements that comprise the columns, or vice versa), and we're also not sure whether the user has passed a value of n corresponding to n rows or n columns:
bool(int **arr, int n){
for(int rows = 0; rows < n; rows++)
for(int cols = 0; cols < n; cols++)
cout << *(*(arr + rows) + cols) << " ";
// Is our next column value encroaching on unallocated memory?
}
cout << endl;
// Is our next row value out of bounds?
}
}
Is there any way to inform this user (before exiting with a segmentation fault), that this function is for printing square 2D arrays only?
Edit: corrected 3rd line from
array[i] = new int[i]
to
array[i] = new int[n]
There is NO way to find out information about an allocation. The ONLY way you can do that, is to store the information about the matrix dimensions somewhere. Pointers are just pointers. Nothing more, nothing less. If you need something more than a pointer, you'll need to define a type that encapsulates all of that information.
class Matrix2D
{
public:
Matrix2D(int N, int M)
: m_N(N), m_M(M), m_data(new int[N*M]) {}
int N() const { return this->m_N; }
int M() const { return this->m_M; }
int* operator[] (int index) const
{ return m_data + m_M * index; }
private:
int m_N;
int m_M;
int* m_data;
};

Looping through 2D array using sizeof() in C++ [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 4 years ago.
I am trying to write a small C++ library to do simple matrix calculations. It consists of a Matrix class with static member functions altering given matrices.
I have one function which adds a scalar to each element, however the loop isn't working:
// Member function to add a scalar to the matrix
void Matrix::add_scal(double** arr, double s) {
for (size_t x = 0; x < sizeof(arr) / sizeof(*arr); ++x) {
Serial.println("test");
for (size_t y = 0; y < sizeof(*arr) / sizeof(**arr); ++y) {
arr[x][y] += s;
}
}
}
"Test" is only printed once and the inner loop isn't run at all. Here is the function I use to create a matrix:
double** Matrix::init(int rows, int cols) {
double** temp = new double*[rows];
for (int i = 0; i < rows; i++) {
temp[i] = new double[cols];
for (int j = 0; j < cols; j++) {
temp[i][j] = 0.0;
}
}
return temp;
}
The following two lines create a matrix and are supposed to add a scalar to it:
double** test = Matrix::init(3, 3);
Matrix::add_scal(test, 2.5);
The loop is not working, because sizeof() is not working as you think it does.
You are asking for the size of pointer, which is always a constant on a given machine (e.g. it is 4 in a 32bit). So, when you ask for the size of *arr, or **arr, that would be a number, irrelevant from the dimensions of the matrix!
In order to verify this yourself, print them, like this:
std::cout <<sizeof(*arr) << " " << sizeof(**arr) << std::endl;
Read more in Is the sizeof(some pointer) always equal to four?
In order to loop over a matrix, you need to use its dimensions, rows and cols in your case, like this:
void Matrix::add_scal(double** arr, double s) {
for (size_t x = 0; x < rows; ++x) {
Serial.println("test");
for (size_t y = 0; y < cols; ++y) {
arr[x][y] += s;
}
}
}
PS: You dynamically allocate the matrix correctly, but do not forget to free the memory when you don't need it any more-it's a must! If you don't know how, check my dynamic 2D array in C++
.
Tip: In C++, I strongly suggest you to use std::vector, which grows and shrinks in size automatically. Moreover, it has a method called size(), which returns the size of it, so you don't need to track its size manually!
In order to create a matrix using vectors, read Vector of Vectors to create matrix.

2D complex array in C++

I am new in C++ programing so I need a help about 2D arrays. Is it possible to create complex array from two real array with two for loops?I was trying to do that in my code but...I do not know how to do that.
Thanks for help!
This is my code::
#include <iostream>
#include <fstream>
#include <complex>
#include <cmath>
using namespace std;
int const BrGr = 15, BrCv = BrGr + 1, BrSat = 24;
//(BrCv=number of nodes,BrSat=number of hours)
int main()
{
// Every array must be dynamic array.It is a task.Is this correct way?
auto *Ipot = new double[BrCv - 1][BrSat];
auto *cosfi = new double[BrCv - 1][BrSat];
auto *S_pot = new complex<double>[BrCv - 1][BrSat];
auto *I_inj = new complex<double>[BrCv - 1][BrSat];
auto *V_cvo = new complex<double>[BrCv][BrSat];
ifstream reader("Input.txt");
if (reader.is_open())
{
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
reader >> Ipot[i][j];
}
}
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
reader >> cosfi[i][j];
}
}
}
else cout << "Error!" << endl;
reader.close();
// Here i want to create 2D array of complex numbers - Is this correct way?
// Also in same proces i want to calculate a value of S_pot in every node for every hour
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
S_pot[i][j] = complex<double>(Ipot[i][j]*cosfi[i][j],Ipot[i][j]*sqr(1-pow(cosfi[i][j],2)));
}
}
// Here i give a value for V_cvo in nodes for every single hour
for (int i = 0;i < BrCv;i++)
{
for (int j = 0;j < BrSat;j++)
{
V_cvo[i][j] = 1;
}
}
// Here i want to calculate a value of I_inj in every node for every hour
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
I_inj[i][j] = conj(S_pot[i][j] / V_cvo[i][j]);
}
}
// Here i want to delete all arrays
delete[] Ipot, cosfi, S_pot, I_inj, V_cvo;
system("pause");
return 0;
Note: I'm using double through out these examples, but you can replace double with any type.
To be honest, you probably don't want to use a 2D array.
Creating a 2D dynamically-sized array in C++ is a multi-stage operation. You can't just
double twoDArray [nrRows][nrColumns];
or
auto twoDArray = new double[nrRows][nrColumns];
There are a couple things wrong with this, but the most important is the rows and columns are not a constant, defined at compile time values. Some compilers allow the first, but this cannot be guaranteed. I don't know if any compiler allows the second.
Instead, First you create an array of rows to hold the columns, then you separately create each row of columns. Yuck.
Here's the set up:
double * arr[] = new double*[nrRows]; // create rows to point at columns
for (size_t index = 0; index < nrRows; index++)
{
arr[index] = new double[nrColumns]; // create columns
}
And here's clean-up
for (size_t index = 0; index < nrRows; index++)
{
delete[] arr[index]; // delete all columns
}
delete[] arr; // delete rows
For your efforts you get crappy spacial locality and the performance hit (Cache miss) that causes because your many arrays could be anywhere in RAM, and you get crappy memory management issues. One screw-up, one unexpected exception and you have a memory leak.
This next option has better locality because there is one big data array to read from instead of many, but still the same leakage problems.
double * arr2[] = new double*[nrRows]; // create rows to point at columns
double holder[] = new double[nrRows* nrColumns]; // create all columns at once
for (size_t index = 0; index < nrRows; index++)
{
arr[index] = &holder[index * nrColumns]; // attach columns to rows
}
and clean up:
delete[] arr2;
delete[] holder;
In C++, the sane person chooses std::vector over a dynamically-sized array unless given very, very compelling reason not to. Why has been documented to death all over SO and the Internet at large, and the proof litters the Internet with hijacked computers serving up heaping dollops of spam and other nastiness.
std::vector<std::vector<double>> vec(nrRows, std::vector<double>(nrColumns));
Usage is exactly what array users are used to:
vec[i][j] = somevalue;
This has effectively no memory problems, but is back to crappy locality because the vectors could be anywhere.
But...!
There is a better method still: Use a One Dimensional array and wrap it in a simple class to make it look 2D.
template <class TYPE>
class TwoDee
{
private:
size_t mNrRows;
size_t mNrColumns;
vector<TYPE> vec;
public:
TwoDee(size_t nrRows, size_t nrColumns):
mNrRows(nrRows), mNrColumns(nrColumns), vec(mNrRows*mNrColumns)
{
}
TYPE & operator()(size_t row, size_t column)
{
return vec[row* mNrColumns + column];
}
TYPE operator()(size_t row, size_t column) const
{
return vec[row* mNrColumns + column];
}
};
This little beastie will do most of what you need a 2D vector to do. You can copy it, you can move it. You can crunch all you want. Jay Leno will make more.
I jumped directly to the templated version because I'm stumped for a good reason to explain class TwoDee twice.
The constructor is simple. You give it the dimensions of the array and it builds a nice, safe 1D vector. No muss, no fuss, and No Zayn required.
The operator() functions take the row and column indices, do a simple bit of arithmetic to turn the indices into a single index and then either return a reference to the indexed value to allow modification or a copy of the indexed value for the constant case.
If you're feeling like you need extra safety, add in range checking.
TYPE & operator()(size_t row, size_t column)
{
if (row < mNrRows && column < mNrColumns)
{
return vec[row* mNrColumns + column];
}
throw std::out_of_range("Bad indices");
}
OK. How does the OP use this?
TwoDee<complex<double>> spot(BrCv - 1, BrSat);
Created and ready to go. And to load it up:
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
Spot(i,j) = complex<double>(7.8*Ipot(i,j),2.3*cosfi(i,j));
}
}
Declaring a dynamic 2D array for a premitive type is the same as for std::complex<T>.
Jagged array:
complex<int> **ary = new complex<int>*[sizeY];
//run loop to initialize
for (int i = 0; i < sizeY; ++i)
{
ary[i] = new complex<int>[sizeX];
}
//clean up (you could wrap this in a class and write this in its destructor)
for (int i = 0; i < sizeY; ++i)
{
delete[] ary[i];
}
delete[] ary;
//access with
ary[i][j];
//assign index with
ary[i][j] = complex<int>(int,int);
It's a little heavier weight than it needs to be, and it allocates more blocks than you need.
Multidimensional arrays only need one block of memory, they don't need one block per row.
Rectangular array:
complex<int> *ary = new complex<int>[sizeX * sizeY];
//access with:
ary[y*sizeX + x]
//assign with
ary[y*sizeX+x] = complex<int>(int,int);
//clean up
delete[] ary;
Allocating just a single contiguous block is the way to go (less impact on allocator, better locality, etc But you have to sacrifice clean and nice subscripting.

Extract rows/columns from ** matrices in C/C++

I have a square matrix double **A
I know how to iterate through this matrix:
for (int i = 0; i < MATRIX_SIZE; i++) {
for (int j = 0; j < MATRIX_SIZE; j ++) {
int val = A[i][j];
printf("val: %d\n", val);
}
}
However, I'm wondering how I can assign an entire row or column to a variable given I have this ** matrix (The ** pointer to pointer nonsense is still a little confusing. I believe its saying a list of list of doubles).
To add a little more background, I'm trying to extract rows and columns so I can perform a cuda matrix multiplication. I see a lot of documentation online that uses one-dimensional vectors to represent matrices (i.e. double* A) However, I am getting confused with the **
A two-dimensional array of doubles (double **) can be looked at as a one-dimensional array of one-dimensional arrays of doubles.
double **arr; // properly initialized
for(int rowNumber = 0; rowNumber < MATRIX_SIZE; ++rowNumber)
{
double *row = arr[rowNumber];
// do something with this row
for(int colNumber = 0; colNumber < MATRIX_SIZE; ++colNumber)
{
double value = row[colNumber];
// do something with value
}
}
In the above example, row is a pointer to a contiguous row of values from the initial array. This works because a two dimensional array is usually allocated like this:
double **arr = new double*[ROW_COUNT];
for(int rowNumber = 0; rowNumber < ROW_COUNT; ++rowNumber)
{
arr[rowNumber] = new double[COL_COUNT];
}
Getting a pointer to a column in the matrix (like we did with row above) is not possible because the values in a column are not contiguous, only the values in each row are contiguous.
In C++, you can use std::array
std::array< std::array<int, MATRIX_SIZE>, MATRIX_SIZE> A;
std::array<int, MATRIX_SIZE> ith_row = A[i];
std::array<int, MATRIX_SIZE> &ith_row_ref = A[i];
A[i][j] is a type of int, but A[i] is a int pointer, so if you want get a row to a variable, you can do this:
for (int i = 0; i < MATRIX_SIZE; i ++) {
int* val = A[i];
for (int j = 0; j < MATRIX_SIZE; j ++) {
printf("%d\n", val[j]);
}
}
but you can't get a column to a variable.
You can assign rows to variables easily but you can't assign columns because of the way that memory is laid out.
You can think of double pointers like this.
The first pointer points to the item to give you the row.
I'm going to make a 3w 4c matrix to show you an example
Theoretical (How you should think about it in your head)
Your first double pointer
p
|
V 0 1 2 <-indexes
0 [p1]->[1,2,3]
1 [p2]->[0,2,3]
2 [p3]->[1,0,3]
3 [p4]->[1,2,0]
which corresponds to the matrix
1,2,3
0,2,1
1,0,3
1,2,0
So you can thinking about getting the 0 at index (1,0) as
int **p = //some place that holds the matrix;
int *row2 = p[1];
int value = p[0];
The reason why it's not as straightforward as declaring a two dimensional
array is because when get the double pointer, you're not sure of the layout of the memory. The numbers could be stored like this
p1 p3 p2 p4
| | | |
[123103021120...] <- //this is basically RAM or "memory"
and you would have no idea as the programmer.
I hope this cleared some things up!

Overload operator to transpose array

I'm tryining overload operator ~ that transpose a given matrix:
Here's my code:
virtual B operator~()const
{
B a(column,row);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.e[i] = e[j];
}
}
return a;
}
e is pointer to the memory storing all integer elements of B
int *const e;
But on the output I've gotten a matrix filled by zeros and with the same size. I mean if I wnat transpose 5x2, I got the same 5x2 filled by zeros.
Edit:
My constuctor:
B(int r, int c)
: row(r), column(c), e(new int[r*c])
{
for (int i = 0; i < r*c; i++)
{
e[i] = 0;
}
}
Your code is not filling a.e properly: rather than transposing the matrix, it keeps overriding a region that corresponds to the same row with numbers for different columns.
Assuming row-major order, the code should be like this:
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.e[j*row+i] = e[i*column+j];
}
}
Since you mention that you've got a result filled with zeros, the logic of your copy constructor and / or the assignment operator may not be coded correctly. Note that since B::e is allocated dynamically, you need a destructor as well.
B a(column,row);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.e[i] = e[j];
}
}
Isn't accessing most of the elements in either this or a. Only element 0 to column and 0 to row respectively are accessed.
The zeroing constructor does not reveal how the row/columns are stored, but a guess would be
int& B::at(int r, int c){
return e[r*column + c];
}
The alternative is
return e[c*row + r];
In this case you can transpose by
virtual B operator~()const
{
B a(column,row);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.at(i, j) = at(j, i); // swap row, column
}
}
return a;
}
First, you seem to always set the first [0..row] elements in the transpose, with the last elements on every row in the original and stop there.
Second, i don't know how B is internally laid, but because you can specify the size of the matrix, i deduce that the internal array that is used to store the elements is allocated dynamically in a one-dimension buffer. This means that you have a copy constructor to avoid problems with the deletion of a at the end of the method. You getting a lot of 0s possibly means (beside the fact that you don't scan the entire matrix), that your copy constructor is not properly implemented.
EDIT Seeing your edit of the question, i tend to be sure that the copy constructor is the problem. You don't have a crash because 5x2 = 2x5 elements (so the internal buffer is the same size).