Overload operator to transpose array - c++

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).

Related

How to delete and reassign a dynamically allocated pointer

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.

Access violation when using delete[] on a 2-dim array [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 2 years ago.
I'm doing a matrix-product exercise (strassen's algorithm actually) using C++. Since the biggest data set given reaches 2048 * 2048, I tried to free the temp memory using delete[]. But it says there is a memory access violation in it, why?
Here are some of the code that may help:
struct Matrix {
int row, column;
int** m;
Matrix(int row, int column) {
m = new int* [2048];
for (int i = 0; i < row; i++)
m[i] = new int[2048];
}
~Matrix() {
if (m != NULL) {
for (int i = 0; i < 2048; i++) {
delete[] m[i]; //access violation happens here
}
delete[] m;
}
}
};
Matrix matAdd(Matrix matA, Matrix matB) {
Matrix matR = Matrix(matA.row, matA.column);
for (int i = 0; i < matA.row; i++)
for (int j = 0; j < matA.column; j++) {
matR.m[i][j] = matA.m[i][j] + matB.m[i][j];
}
return matR;
}
//There are some other functions below but the structure is basically the same
The pointers in the array, starting from the index row were not initialized.
Matrix(int row, int column) {
m = new int* [2048];
for (int i = 0; i < row; i++)
m[i] = new int[2048];
// Initialize rest elements with null pointer.
for (int i = row; i < 2048; i++)
m[i] = nullptr;
}
The rest initialization will fix the crash, but then you will get crash on double free. The reason: you use copies of your class, thus you need to implement the copy constructor and the assignment operator or use shared pointers instead of raw pointers. The default copy makes pointers pointing to the same allocated objects.
Also look at the answer https://stackoverflow.com/a/1403180/6752050 with the example how to create a 2d matrix with a single allocation.
You should consider using std::vector<std::vector<int>>.
Your class is lacking copy constructor and copy assignment and I am certain it is a case of double free.

Trying to copy a 2D dimensional array of objects to another function

I'm trying to copy an array from one class to to another class by passing it to a function but I'm running into issues. The array that I'm trying to copy seems to lose all its data.
// A.h
class A
public:
virtual void Test();
private:
A* array2D[30][32];
// A.cpp
void A::Test()
{
B* f = new B();
f->pass(array2D);
}
// B.h
class A;
class B
{
public:
void pass(A *a[][32]);
private:
A *a[30][32];
}
// B.cpp
void B::pass(A *array2D[][32])
{
for (int i = 0; i <= 30; i++)
{
for (int j = 0; j <= 32; j++)
{
a[i][j] = array2D[i][j];
}
}
}
My guess is that it's happening when I'm passing it but I'm not sure what I'm doing wrong.
My guess is that it's happening when I'm passing it but I'm not sure what I'm doing wrong.
First, your for loops to populate the array go out-of-bounds on the last iteration of the nested for loop:
void B::pass(A *array2D[][32])
{
for (int i = 0; i <= 30; i++) // This goes out-of-bounds on the last iteration
{
for (int j = 0; j <= 32; j++) // This also goes out-of-bounds.
{
a[i][j] = array2D[i][j];
}
}
}
Using <= in a for loop is an indication that things can go wrong, and they do go wrong with your code. The fix would simply be:
void B::pass(A *array2D[][32])
{
for (int i = 0; i < 30; i++)
{
for (int j = 0; j < 32; j++)
{
a[i][j] = array2D[i][j];
}
}
}
This will work, however it is inefficient (unless a great optimizing compiler sees that this is inefficient and changes the code).
The better way to do this is a simple call to std::copy:
#include <algorithm>
void B::pass(A *array2D[][32])
{
std::copy(&array2D[0][0], &array2D[29][32], &a[0][0]);
}
The reason why this works is that two-dimensional arrays in C++ have their data layout in contiguous memory, thus it is essentially a one-dimensional array. So giving the starting and ending address of the array elements is all that's required.
A compiler will more than likely see that you are copying a trivially-copyable type (a pointer), thus the call to std::copy results in a call to memcpy.

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;
};

Cant free memory

In code:
template<class T,int row, int col>
void invert(T (&a)[row][col])
{
T* columns = new T[col * row];
T* const free_me = columns;
T** addresses = new T*[col * row];
T** const free_me_1 = addresses;
/*cpy addresses*/
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < col; ++j)
{
*addresses = &a[i][j];
++addresses;
}
}
addresses = free_me_1;
/*cpy every column*/
for (int i = 0; i < col; ++i)
{
for (int j = 0; j < row; ++j)
{
*columns = a[j][i];
++columns;
}
}
columns = free_me;
/*cpy from columns to addresses*/
for (int i = 0; i < (col * row); ++i)
{
*addresses[i] = columns[i];
}
delete[] free_me_1;
delete[] free_me;
}
I've observed that while iterating, value of variable columns equals zero and I think thats the problem.
Thanks for your help.
P.S. I've pasted final version of this fnc. It works as intended now. Thank you everyone for your valuable help.
You write past the buffer end because the buffer is too small.
T* columns = new T[col];
should be
T* columns = new T[col*row];
Writine past the buffer end is undefined behavior - in your case it's heap corruption because you overwrite some service data essential for the heap functioning and so delete[] fails.
You initialize columns as a new T[col]. Then you increment columns in the inner loop, which gets execute col*row times - unless rows==1, you increment columns past the end of the array you've allocated, causing undefined behaviour.
Note that even once you fix that, your function is still very wrong - it has neither a return value nor side effects. It should be a no-op. It definitely doesn't invert its parameter.