I'm trying to add two polynomials stored in a 2D array with the first rows store the coefficients and the second row store the degree.
I created a overloading + function but here I use 2D allocated memory array and it crashes when the function is called.
**Update: it runs now but the results are some big negative numbers
FYI, I have a copy constructor and an overloading = operator
// overload +
Polynomial Polynomial::operator+(const Polynomial &right)
{
maxExp = right.maxExp;
poly = new int *[maxExp];
for (int i=0; i < maxExp; i++)
*(poly + i) = new int[2];
Polynomial temp = *this;
for (int i=0; i < maxExp; i++)
{
for (int j=0; j < 2; j++)
{
temp.poly[i][j] = poly[i][j] + right.poly[i][j];
}
}
return temp;
}
just start with += and copy operators and make the + operator form that.
There are multiple problems, but the most glaring one is that the very first line:
delete [] poly;
destroys one of the summands (the x in x + y). It also leaks memory, but at this point this is secondary.
edit: I notice that you've edited the delete[] out of your question. This doesn't fix the problem, but makes it worse: you're still overwriting the summand, but now are leaking even more memory.
Related
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.
I'm trying to delete my 2D array, but I consistently get errors when I try to delete it, we have to work backwards so I delete the elements first, then the column array, then the row array. here is my code for the constructor in my class, MyMatrix:
private:
int m; //rows
int **ptr; //ptr to first dimension
int n; // columns
public:
MyMatrix() //constructor
{
m = 0;
n = 0;
ptr = new int*[m];
int *length_arr = new int[m];
for (int i = 0; i <= m-1; i++)
{
*(ptr+i) = new int[n];
*(length_arr+i) = n;
}
}
and my destructor looks like this:
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
the error I'm getting is:
assg7(2677,0x100de3d40) malloc: *** error for object 0x12d606804: pointer being freed was not allocated
I've wracked my brain for where I can fix this, for context, I'm doing an assignment with operator overloading. I specifically need a delete function to work properly for my = assignment overloading since I want to delete and again reallocate memory to equate two matrices, but the terminal is showing malloc errors and is thus not equating the matrices.
for additional info here is my = overloading code:
void operator = (const MyMatrix &obj)
{
if(n == obj.n && m == obj.m)
{
//for loop to equate elements in this-> to the elements of the passed object
}
else
{
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
// the code for assigning new memory according to the passed objects rows and colums goes here
//then for loop to equate elements in this-> to the elements of the passed object
}
}
thanks.
You have two "levels" of new, so three "levels" of delete can't be right.
Spell out your deletion loop, using indexing instead of pointer arithmetic:
First iteration:
delete ptr[0]+0;
delete ptr[0]+1;
...
delete ptr[0]+n-1;
delete [] ptr[0];
Second iteration:
delete ptr[1]+0;
delete ptr[1]+1;
...
delete ptr[1]+n-1;
delete [] ptr[1];
You're passing to delete a pointer to the first element of ptr[0], a pointer to the second element of ptr[0], a pointer to the third element of ptr[0], ...
But the things you allocated were ptr[0], ptr[1], ... ptr[m-1], not their individual elements.
Remove the innermost deletion loop.
(And don't mess around with pointer arithmetic when you can use indexing.)
I don't know how you would want to allocate memory space by m length if it is set to 0 by default.
To me it looks like you set m = 0 and then try to allocate by 0 length or how do you control the length of your dimensions?
Maybe edit your constructor to:
MyMatrix(int m, int n)
{
this->m = m;
this->n = n;
...
I'm making vector objects and using operator overloading so that they can be added, subtracted etc. easily. At present, my operator functions all calculate a resulting vector and return it. In the case of all vectors, the elements are heap allocated, and this happens in the constructor, so the resultant vector is heap allocated as well. Now I've run into an issue. Suppose I wanted to compute the following (assuming addition and multiplication operator overload functions work as I stated).
vector x = vector(3);
vector y = vector(3);
vector z = x + 2*y
delete x;
delete y;
delete z;
What should I do for this to not cause a memory leak? As it stands, my code would create a new vector in memory for 2*y and that would just be left there, not being assigned to everything. Is there any alternate approach that would prevent this?
It's possible this doesn't cause a memory leak though I'm not sure how to find that out (new to c++), I'm just assuming it will based off the fact that 2*y allocates memory and isn't deleted.
Below are my definitions for vector addition and scalar multiplication and the constructor.
vector(int dim) {
n=dim;
vals = new float[n];
}
vector operator + (const vector y) {
assert(y.n == n); // n is number of elements
vector z = vector(n);
for(int i = 0; i < n; i++) {
z.vals[i] = vals[i] + y.vals[i]; // vals is a heap allocated array
}
return z;
}
vector operator * (const float c) {
vector z = vector(n)
for(int i = 0; i < n; i++) {
z.vals[i] = c*z.vals[i];
}
return z;
}
In short, I was assigned the task of creating a class that dynamically allocates memory to form a matrix of int values.
Part of the class are member functions that perform the basic matrix calculations -- addition, subtraction, and multiplication. Everything compiles (on my end at least), but when I used a driver to test the multiplication portion, it keeps crashing.
I'm using Codeblocks as my IDE and haven't had much luck with the debugger there in trying to figure it out. It appears that the calculation completes (with correct values), but then things go horribly wrong somewhere.
For clarity, each object of the Matrix class has the following member data:
private:
int rows;
int cols;
int **element;
Below is a snippet of the implementation file in which the overloaded operator* is fleshed out. The portion where temp.element[i][x] is set to '0' before the loop performing the multiplication is commented out because the default constructor already sets all values to '0' -- which I had forgotten when I put it in originally. It didn't work when I didn't have it commented out either.
In testing, I used one 2x3 array and one 3x2 array.
Matrix Matrix::operator*(const Matrix &aMatrix) const
{
if(cols == aMatrix.rows)
{
Matrix temp(rows, aMatrix.cols);
for(int i = 0; i < rows; i++)
{
for(int x = 0; x < aMatrix.cols; x++)
{
//temp.element[i][x] = 0;
for(int n = 0; n < cols; n++)
{
temp.element[i][x] += (element[i][n]
* aMatrix.element[n][x]);
}
}
}
return temp;
}
else
{
cerr << "Matrix multiplication failed -- incompatible matrix sizes."
<< endl;
return *this;
}
}
Upon trying to go through the code and find errors, I started re-checking the other functions I had. It appeared that both addition and subtraction worked, but the program would close if the matrices were incompatible (ie. trying to add a 2x3 and a 4x4).
Below is the snippet for the addition (subtraction is almost identical just '-' instead of '+' in the final loops.
Matrix Matrix::operator+(const Matrix &aMatrix) const
{
if(rows == aMatrix.rows && cols == aMatrix.cols)
{
Matrix temp(rows, cols);
for(int i = 0; i < rows; i++)
{
for(int x = 0; x < cols; x++)
{
temp.element[i][x] = element[i][x] + aMatrix.element[i][x];
}
}
return temp;
}
else
{
cerr << "Undefined matrix addition -- matrices are different sizes."
<< endl;
return *this;
}
}
Any help or insight is appreciated. Thanks.
EDITED: Added overloaded assignment operator, copy constructor, and destructor code.
Below is the overloaded assignment operator:
Matrix Matrix::operator=(Matrix aMatrix)
{
if(this != &aMatrix)
{
for(int i = 0; i < rows; i++)
{
delete [] element[i];
element[i] = NULL;
}
delete [] element;
rows = aMatrix.rows;
cols = aMatrix.cols;
element = new int* [rows];
for(int i = 0; i < rows; i++)
{
element[i] = new int [cols];
for (int x = 0; x < cols; x++)
{
element[i][x] = aMatrix.element[i][x];
}
}
}
return *this;
}
Below is the copy constructor:
Matrix::Matrix(const Matrix &aMatrix)
{
rows = aMatrix.rows;
cols = aMatrix.cols;
element = new int* [rows];
for(int i = 0; i < rows; i++)
{
element[i] = new int [cols];
for (int x = 0; x < cols; x++)
{
element[i][x] = aMatrix.element[i][x];
}
}
}
Destructor:
Matrix::~Matrix()
{
for(int i = 0; i < rows; i++)
{
delete [] element[i];
element[i] = NULL:
}
delete [] element;
element = NULL;
}
You posted a copy constructor and assignment operator. Your assignment operator has 4 major issues:
You should pass the parameter by const reference, not by value.
You should return a reference to the current object, not a brand new object.
If new throws an exception during assignment, you've messed up your object by deleting the memory beforehand.
It is redundant. The same code appears in your copy constructor.
You can rewrite the assignment operator in terms of the copy constructor and alleviate these issues:
#include <algorithm>
//...
Matrix& Matrix::operator=(const Matrix& aMatrix)
{
Matrix temp(aMatrix);
swap(*this, temp);
return *this;
}
void Matrix::swap(Matrix& left, Matrix& right)
{
std::swap(left.rows, right.rows);
std::swap(left.cols, right.cols);
std::swap(left.element, right.element);
}
You just need to add the swap function to your Matrix class (probably as a private) function.
The code above uses the copy/swap idiom, and alleviates all of the issues I mentioned. This will work provided that your copy constructor and destructor are written properly. There are many threads on SO that talk about this idiom, but basically what is happening is this:
Create a temporary object from the passed-in object. If there is a problem with new throwing, your this doesn't get messed up.
Swap out this's members with the temporaries members. This refreshes the this object with the temporary's data, and gives the temporary the old data we don't need any more.
Let the temporary die with the old stuff we gave it from this.
Return this.
As to the other aspects, if the two Matrices cannot be multiplied, then just throw an exception. Do not return a bogus or confusing Matrix object that doesn't really reflect what happened.
In addition, you should first write operator += and *=. Why? Because implementing operator + and * can be done in terms of += and *=, respectively, plus you get the added bonus of having += and *= available.
For example:
Matrix& Matrix::operator+=(const Matrix &aMatrix)
{
if(rows != aMatrix.rows || cols != aMatrix.cols)
throw SomeException;
for(int i = 0; i < rows; i++)
{
for(int x = 0; x < cols; x++)
element[i][x] += aMatrix.element[i][x];
}
return *this;
}
Matrix Matrix::operator+(const Matrix &aMatrix)
{
Matrix temp(*this);
temp += aMatrix;
return temp;
}
So if the Matrix sizes are an issue, operator + and += will throw an exception. Note how operator + is implemented in terms of +=. Take the same approach to *, *=, and also - and -=.
You need to figure out what the syntax and semantics are of these operations. It looks from your example as though you want something like:
Matrix lhs = <something>;
Matrix rhs = <something>;
Matrix result = lhs * rhs;
to "just work". While this might be nice syntactically, you need to account for what happens if lhs and rhs can't be multiplied (or added, etc.) You also need to worry about setting up the result properly. You can't just return a "struct consisting of number of rows, columns and an array of pointers" and expect not to run into horrific memory management problems.
What will be responsible for making the product disappear? When it goes out of scope? C++ is not a very good language for linear algebra.
The first decision that you need to make is whether you intend to throw an exception for invalid operations, or return some indication of what went wrong, perhaps bool and a const char * to an error message.
Then you probably should try writing a function taking a result reference and 2 operand references, and just get the basic algebra right, if the matrices support the operation. (I have not mentioned yet that your Matrix is an integer matrix only.)
In "real life", you would probably try to find an open source standard solution that manages all of this, because numerical operations need to be managed very carefully.
One might even go so far as to suggest that this is a problem that has already been capably solved decades ago in Fortran, and to this day, if performance is an issue, there is a good chance that the underlying calculations might be in Fortran, or a library that was a port from C.
I am struggling to get my head around operator overloading. In this case the + operator I have and example of what I have tried, any help would be greatly appreciated.
I am getting an error which says "invaild use of 'class Matrix' I am unsure on how to fix this how can I add these two Matrix objects together?
Matrix Matrix::operator+(const Matrix& rhs){
return Matrix(Matrix + rhs.Matrix());
}
Matrix::Matrix(int MM, int NN){
M = MM;
N = NN;
data = new double[M * N];
for ( int i =0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
data[i* N+j] = (double) 1000 + i*N+j;
// cout << data[i*N+j] <<"\t";
}
//cout <<"\n";
}
cout << "Matrix Constructor... (code to be implemented here!!!)\n";}
Thanks
rhs is a Matrix
calling a constructor like a method is very illegal
in Matrix + rhs, Matrix is not an identifier
Once you get your identifiers straightened out, *this + rhs is equivalent to this->operator+(rhs). It should be obvious from this that all you've done here is create an infinite recursion.
jpm's answer is very important to look at. Once you've fixed these things, you can look at mine.
Essentially, an operator overload is no different than any other function.
So, in the case of:
Matrix Matrix::operator+(const Matrix& rhs)
What you're really doing there is saying: add rhs to the current matrix, and return a new matrix. Your overload should not alter the current matrix. Help yourself and use a constant:
Matrix Matrix::operator+(const Matrix& rhs) const
A matrix addition like that should first check if the matrices have the same dimensions so that you can add them together, then loop through all "cells" and add them, and create a matrix out of that. For that, I'm guessing you'll need a second constructor, something like:
Matrix::Matrix(int MM, int NN, double values[])
{
M = MM;//TODO: change to width
N = NN;//TODO: change to height
data = new double[M*N];
for(int i < 0; i < M; i++)
for(int j < 0; j < N; j++)
data[i * N+j] = values[i * N+j];
}
return Matrix(Matrix + rhs.Matrix());
^^^^^^ ^^^^^^
You're using a type name (Matrix) where there should be an expression - that's what the compiler is complaining about. You're also trying to call the constructor on an existing object, which is invalid (and nonsensical). You also seem to be trying to implement operator+ in such a way that it calls itself; if you do somehow make it compile, then it will cause a stack overflow due to infinite recursion.
Perhaps the easiest way to implement addition is to implement operator+= to add one matrix to an existing one, and then implement operator+ in terms of that:
Matrix & Matrix::operator+=(Matrix const & rhs) {
// Perform addition here
for (int i = 0; i < N*M; ++i) {
data[i] += rhs.data[i];
}
return *this;
}
// This can be a non-member function
// Pass "lhs" by value to get a copy, then modify and return that.
Matrix operator+(Matrix lhs, Matrix const & lhs) {
return lhs += rhs;
}
// Or if you really want a member function for some reason
Matrix Matrix::operator+(Matix const & rhs) const {
return Matrix(*this) += rhs;
}
This does require you to have a correct copy constructor - since you're allocating memory yourself in the constructor, and presumably deallocating it in the destructor, you must implement a copy-constructor to correctly allocate new memory (per the Rule of Three), otherwise you'll get a double-deletion after copying a matrix.