I'm trying to set some overloading operator functions for matrices where I used the constructor to dynamically allocate them, and an istream operator for setting values. I have encountered a problem when trying to multiply two matrices (run time error).
Any help would be appreciated.
ps: I'm not familiar with templates.
Here is my * operator function:
matrixType operator*(matrixType m)
{
if( Rows==m.Cols && Cols==m.Rows)
{
matrixType m3(Rows,m.Cols);
for( int i=0; i<Rows;i++)
{
for( int j=0; j<Cols; j++)
{
{
for(int g=0; g<Cols;g++)
m3.matrix[i][j]+=matrix[i][g] * m.matrix[g][j];
}
}
}
return m3;
}
}
And here is my copy operator function:
matrixType& operator=( matrixType& m)
{
for (int i =0; i<Rows; i++)
{
for ( int j=0; j<Cols; j++)
matrix[i][j]=m.matrix[i][j];
}
return *this;
}
I think it would be better if you post some runtime error when you run the code. Anyway, I found a problem in your Multiply operator function:
when you return m3, it is defined in another scope, therefore it is not defined, how about you put return m3 statement inside the if scope:
matrixType operator*(matrixType m)
{
if( Rows==m.Cols && Cols==m.Rows)
{
matrixType m3(Rows,m.Cols);
for( int i=0; i<Rows;i++)
{
for( int j=0; j<Cols; j++){
{for(int g=0; g<Cols;g++)
m3.matrix[i][j]+=matrix[i][g] * m.matrix[g][j];}
}
return m3;
}
// Throw some error if your assertion is not satisfied, perhaps
}
}
You're using the wrong Cols in your j loop. You want m.Cols there:
for (for( int j=0; j<m.Cols; j++)
Look at where the i, j, and g variables are used for subscripting to see what the limit values are for the 3 loops.
Related
cannot convert 'brace-enclosed initializer list>' to 'int' in assignment
as explained above, line 19 and 20, specifically when I described the content of the array, the compiler told me the line above. I know it is a long code, and I will appreciate your answers.
I guess that's as detailed as I could.
#include <iostream>
using namespace std;
class matrix{
private:
static const int x =3;
int m1[x][x];
int m2[x][x];
int c[x][x];
public:
matrix(){
int m1[x][x];
int m2[x][x];
int c[x][x];
c[x][x];
}
matrix(int m1[x][x], int m2[x][x], int c[x][x]){
m1[x][x]= {{1,2,3},{4,5,6},{7,8,9}};
m2[x][x]= {{10,11,12},{13,14,15},{16,17,18}};
c[x][x];
}
matrix operator+(matrix& m2){
matrix result;
for( int i=0; i<x; i++){
for(int j=0; j<x; j++){
result.m1[i][j];
result.m2[i][j];
result.c[i][j] = result.m1[i][j] + result.m2[i][j];
}
}
return result;
}
matrix operator-(matrix& m2){
matrix result;
for( int i=0; i<x; i++){
for(int j=0; j<x; j++){
result.m1[i][j];
result.m2[i][j];
result.c[i][j] = result.m1[i][j] - result.m2[i][j];
}
}
return result;
}
matrix operator*(matrix& m2){
matrix result;
for( int i=0; i<x; i++){
for(int j=0; j<x; j++){
result.m1[i][j];
result.m2[i][j];
result.c[i][j] = result.m1[i][j] * result.m2[i][j];
}
}
return result;
}
friend ostream& operator <<(ostream& outs, const matrix& m){
outs << m<< endl;
return outs;
}
};
int main(){
matrix m1;
matrix m2;
cout <<m1+m2<<endl;
return 0;
}
As already said this code is just wrong from top to bottom. It really should be thrown away. Let fix the most basic error. class matrix represents a 3x3 matrix. So it should be written like this
class matrix
{
private:
static const int x = 3;
int elem[x][x]; // the elements of a 3x3 matrix
public:
... // more code
};
In your version
class matrix
{
private:
static const int x =3;
int m1[x][x];
int m2[x][x];
int c[x][x];
public:
... // more code
};
the class has three different 3x3 matrices. That isn't right.
So throw your code away, start again with class like the one I've written above.
Here's how operator+ looks with my version of the class
matrix operator+(const matrix& m2) {
matrix result;
for (int i=0; i<x; i++) {
for (int j=0; j<x; j++) {
result.elem[i][j] = elem[i][j] + m2.elem[i][j];
}
}
return result;
}
It's really hard to understand what you are trying to do, You have parameters in the constructor and then you are reinitializing them again.
But I can help you with the way to initialize 2d Matix using the initializer list
matrix():m1{{1,2}, {3, 4}} ,...{}
i have this class
class Matrix
{
int size;
std::unique_ptr<std::unique_ptr<int[]>[]> val;
public:
Matrix(int size1)
{
size=size1;
val=std::make_unique< std::unique_ptr<int[]>[] >(size);
...
}
... move constructor,move assignment operator
Matrix& operator+(Matrix &m)
{
Matrix sumMatrix(size);
for ( int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j){
sumMatrix.val[i][j]=this->val[i][j]+m.val[i][j];
}
}
return sumMatrix;
}
and main :
...
Matrix e=b+c;
std::cout<<"e="<<std::endl;
e.print();
and i have this error :
warning: reference to local variable 'sumMatrix' returned
[-Wreturn-local-addr]
Matrix sumMatrix(size);
Can someone please help me with this ??
Return by value, as you should for operator+ most of the time:
// vvv--Removed & vvvvv-----vvvvv--Const is more appropriate here
Matrix operator+(Matrix const &m) const { ... }
This will require a copy constructor, make sure to add that. Also note that you should probably collect your for-loop logic into an operator+= and simplify operator+ significantly while providing more functionality for the end-user:
Matrix& operator+=(Matrix const& m) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
//vvv--No need for this-> in C++
val[i][j] += m.val[i][j];
}
}
return *this;
}
Matrix operator+(Matrix const& m) const {
Matrix sumMatrix{m}; // requires a copy constructor.
sumMatrix += *this;
return sumMatrix;
}
enter image description here
I'm trying to set up my functions and perform some overloading operations so that I can +,-,==,* two matrices. I have encountered a problem at the first operation overload: addition.
My program works until i try to add 2 matrices.
Thanks for help.
include<iostream>
using namespace std;
class matrixType
{
private:
int rows,cols;
int** matrix;
public:
matrixType( int r, int c)
{
rows=r;
cols=c;
matrix = new int*[rows];
for(int i = 0; i < rows; ++i)
matrix[i] = new int[cols];
}
~matrixType()
{
for(int i = 0; i < rows; ++i)
{
delete [] matrix[i];
}
delete [] matrix;
}
matrixType operator+( matrixType m2 )
{
if( rows==m2.rows && cols==m2.cols)
{
matrixType m3(rows, cols);
for( int i=0; i<rows; i++)
{
for( int j=0; j<cols; j++)
{
m3.matrix[i][j]=matrix[i][j]+m2.matrix[i][j];
}
}
return m3;
}
}
matrixType operator-(matrixType m2)
{
if( rows==m2.rows && cols==m2.cols)
{
matrixType m3(rows, cols);
for( int i=0; i<rows; i++)
{
for( int j=0; j<cols; j++)
{
m3.matrix[i][j]=matrix[i][j]-m2.matrix[i][j];
}
}
return m3;
}
}
friend istream& operator>> (istream& stream, matrixType m)
{
for ( int i=0; i<m.rows;i++)
{
for( int j=0; j<m.cols;j++)
{
cout<<"Matrix"<<"["<<i<<"]"<<"["<<j<<"]"<<"=";
stream>>m.matrix[i][j];
cout<<endl;
}
}
return stream;
}
friend ostream& operator<<(ostream& out, matrixType m)
{
for ( int i=0; i<m.rows;i++)
{
for( int j=0; j<m.cols;j++)
{
cout<<"Matrix"<<"["<<i<<"]"<<"["<<j<<"]"<<"=";
out<<m.matrix[i][j];
cout<<endl;
}
}
return out;
}
};
Totally different approach as alternative - based on templates:
template <size_t Rows, size_t Columns>
class Matrix
{
int matrix[Rows][Columns];
public:
void operator+=(Matrix<Rows, Columns> const& other)
{
for(size_t i = 0; i < Rows; ++i)
{
for(size_t j = 0; j < Columns; ++j)
{
matrix[i][j] += other.matrix[i][j];
}
}
}
Matrix<Rows, Columns>
operator+(Matrix<Rows, Columns> const& other) const
{
Matrix<Rows, Columns> result(*this);
result += other;
return result;
}
template<size_t C>
Matrix<Rows, C> operator*(Matrix<Columns, C> const& other) const
{
// just exemplary, actual implementation missing:
return Matrix<Rows, C>();
}
// rest of operators coming here
};
It might or might not fit your needs, but if it does, you get the rule of three for free. Additionally you are prevented automatically from adding or multiplying matrices of non-fitting sizes.
On the other hand -- well, benefits always come with some cost, too... -- you lose flexibility. Imagine you want to place arbitrary matrices into a vector - you'd need a base class then and would have to use (smart?) pointers, adding or multiplying arbitrary matrices requires casts, ...
Biggest drawback, though, is that you need to know your matrix sizes at compile time - if you don't, we are out.
By the way, adding/multiplying - in your original implementation, you do not return anything if matrix sizes do not match! You should return some kind of sentinel then, e. g. a 0x0 matrix - or possibly even better: throw some appropriate exception.
This sound like a case of rule of three violation.
You need to implement a copy constructor:
matrixType(const matrixType&)
And a copy assignment operator:
matrixType operator=(const matrixType&)
And for C++11 it might be a good idea to also implement the move constructor and move assignment operator.
matrixType(matrixType&&)
matrixType& operator=(matrixType&& other)
Im trying to to use operator overloading with both + and = operator on a matrix class which i created. either the constructor or destructor is causing a problem or it isn't either (though i grayed out each of them and both and the code seems to work). could someone please help me understand what is causing this strange behavior. when i try to create 3 matrixes a b and c then try a = b+c; it just fails.
header file
#ifndef MATRIX_H;
#define MATRIX_H;
using namespace std;
enter code here
class matrix
{
friend ostream& operator<< (ostream&, matrix &);
public:
matrix();
matrix(int,int); //constructor
matrix(const matrix&);//copy constructor
~matrix();
int getRow();
int getCol();
void setRow(int);
void setCol(int);
class arr1D{ //proxy class to allow the use of [][] operator
public:
arr1D(int* a):temp(a){}
int &operator[](int a){
return temp[a];
}
int *temp;
};
arr1D operator[](int a){
return arr1D(arr2[a]);
}
matrix& operator=(const matrix& );
matrix& operator+(const matrix& );
protected:
private:
int row , col;
int **arr2;
};
#endif // MATRIX_H
enter code here
cpp file
#include <iostream>
#include "matrix.h"
using namespace std;
matrix::matrix()
{
setCol(0);
setRow(0);
**arr2=0;
}
matrix::matrix(int x, int y) //matrix constructor creates x*y matrix and initializes to 0's
{
setCol(y);
setRow(x);
arr2 = new int * [getRow()];
if (arr2) {
for (int i = 0; i < getRow(); i++) {
arr2[i] = new int [getCol()];
};
};
for (int i=0; i<getRow();i++){
for (int j=0;j<getCol();j++){
arr2[i][j]=0;
};
};
}
matrix::matrix(const matrix &m){ //defines the copying constructor
row=m.row;
col=m.col;
arr2 = new int*[row];
for (int i=0; i<row; i++){
arr2[i] = new int[col];
}
for (int i=0; i<row; i++){
for (int j=0; j<col; j++){
arr2[i][j] = m.arr2[i][j];
}
}
}
matrix::~matrix(){ //defines the destructor
for (int i=0; i<row; i++){
delete[] arr2[i];
}
delete[] arr2;
}
int matrix::getRow(){ //getter for row
return row;
}
int matrix::getCol(){ // getter for col
return col;
}
void matrix::setRow(int x){ //setter for row
row=x;
}
void matrix::setCol(int x){ //setter for col
col=x;
}
ostream& operator<< (ostream& output, matrix& a){
int i,j;
for (i=0; i < a.getRow() ; i++){
for (j=0; j< a.getCol() ; j++){
output << " " <<a.arr2[i][j];
};
output << "\n";
};
return output;
}
matrix& matrix::operator=(const matrix& right)
{
if (this == &right) { // Same object?
return *this;
}
row = right.row;
col = right.col;
for (int i=0; i<row; i++)
{
for (int j=0; j<col; j++){
arr2[i][j]=right.arr2[i][j];
}
}
return *this ;
}
matrix& matrix::operator+(const matrix& right)
{
int row=right.row;
int col=right.col;
matrix result(row,col);
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
//cout<<"arr2[i][j]="<<arr2[i][j]<<endl;
//cout<<"right.arr2[i][j]="<<right.arr2[i][j]<<endl;
result.arr2[i][j]=(arr2[i][j] + right.arr2[i][j]);
//cout<<"result.arr2[i][j]="<<result.arr2[i][j]<<endl;
};
};
return result;
}
First, as the other answer pointed out, you are returning a reference to a temporary in your operator +. That is undefined behavior.
But instead of writing operator + in this fashion, what you should do is write operator += instead, and then in turn, write operator + in terms of operator +=. Since a programmer would expect += to also work for the matrix in addition to +, it makes no sense to leave out +=.
For operator +=, you would in this case return a reference to the current object.
So all we need to do is move the code in operator + to operator +=:
#include <exception>
//...
matrix& matrix::operator+=(const matrix& right)
{
if(row != right.row || col != right.col)
throw std::logic_error("Matrix not the same size");
for (int i = 0; i < right.row; i++)
{
for (int j = 0; j < right.col; j++)
arr2[i][j] += right.arr2[i][j]);
}
return *this;
}
Note that we return a reference to the current matrix, since += modifies the current matrix. Also note that we throw an exception on an illegal matrix being sent to +=. This IMO makes more sense than returning a legitimate matrix back on error. If the matrix is not the same size, the code should not try and return a matrix back.
Now operator + can be written in terms of +=:
matrix matrix::operator+(const matrix& right)
{
return matrix(*this) += right;
}
Believe it or not, that's it. All we did was create a temporary matrix and call += with the passed in argument. We return the result of this as a brand new matrix, just as we expect.
The other issue is the assignment operator. Given that you've written a copy constructor and destructor, and the copy constructor works without having to use the assignment operator, then the copy / swap idiom can be used to implement the assignment operator.
#include <algorithm>
//...
matrix& matrix::operator=(const matrix& right)
{
matrix temp(right);
std::swap(temp.arr2, arr2);
std::swap(temp.row, row);
std::swap(temp.col. col);
return *this;
}
All we did here was create a temporary matrix of the passed in object and swap out its contents with the current object's contents. When the temporary dies off at the return, the temporary destroys the old contents that were swapped out.
This method has the advantage of not only being very simple to implement (just a bunch of calls to std::swap), it is also exception safe. If there is an issue creating the temporary matrix, a std::bad_alloc exception would have been thrown, without messing up or altering any members of this. The issue with the other answer given, where you're deallocating the memory first before allocating the new memory, is solved by using the above technique.
I created a class called Matrix with a 2D array. I can run it with the constructor, copy constructor and destructor. When I introduce the unary negation operator, I get a run time error.
https://gist.github.com/anonymous/7823794
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
Matrix(int rSize=3, int cSize=3);
Matrix(const Matrix& m);
~Matrix();
bool setValue(int rSize, int cSize, int value);
bool getValue(int rVal, int cVal, int& value)const;
const Matrix operator- ();
private:
int rowSize;
int columnSize;
int** arr;
};
#endif
#include<iostream>
#include"Matrix.h"
using namespace std;
Matrix::Matrix(int rSize,int cSize)
{
columnSize = cSize;
rowSize = rSize;
arr = new int* [rowSize];
for(int i=0; i<rowSize; i++)
arr[i] = new int[columnSize];
for(int j=0; j<rowSize; j++)
{
for(int k=0; k<columnSize; k++)
arr[j][k] = 0;
}
}
Matrix::Matrix(const Matrix& m)
{
columnSize = m.columnSize;
rowSize = m.rowSize;
arr = new int* [rowSize];
for(int i=0; i<rowSize; i++)
{
arr[i] = new int [columnSize];
}
for(int i=0; i<rowSize; i++)
{
for(int j=0; j<columnSize; j++)
arr[i][j] = m.arr[i][j];
}
}
Matrix::~Matrix()
{
for(int i = 0; i < rowSize; ++i)
delete [] arr[i];
delete [] arr;
}
bool Matrix::setValue(int rVal, int cVal, int value)
{
if((rVal<0)||(cVal<0)||(rVal>rowSize-1)||(cVal>columnSize-1))
return false;
arr[rVal][cVal] = value;
return true;
}
bool Matrix::getValue(int rVal, int cVal, int& value)const
{
if((rVal<0)||(cVal<0)||(rVal>rowSize-1)||(cVal>columnSize-1))
return false;
value = arr[rVal][cVal];
return true;
}
const Matrix Matrix:: operator- ()
{
Matrix m(*this);
for (int i = 0; i< rowSize; i++)
{
for(int j=0; j<columnSize; j++)
m.arr[i][j] = (this->arr[i][j])* -1 ;
}
return m;
}
#include<iostream>
#include"Matrix.h"
using namespace std;
void main()
{
Matrix m(4, 5);
Matrix m2(m);
m2.setValue(1,2,12);
int x;
m2.getValue(1,2,x);
Matrix m3;
m3 = -m2;
}
Edit: Following #unwind and #interjay advice, I implemented the assignment operator first and returned a value, not a reference, for the negation operator and it works. Thank you all for your help
You don't have an assignment operator in your class, which will cause double deletion of the member pointer after an assignment (and you're assigning in the line m3 = -m2;).
You should obey the rule of three.
unwind is also correct that the negation operator should return by value: You should never return a reference to a local variable from a function as that leads to undefined behavior.
Declaring the operator to return const Matrix& and then returning a local variable is wrong. That's a dangling reference, surely?
See for reference this answer where the operator returns an actual new value, not a reference. This makes a lot more sense to me.