trying to define a friend function which add two matrix

Hello there!
i am a beginner user of c++
i am trying to write a code which get two different matrix and add them together
i dont know why the output of the friend function in my code dont work
it print "Process returned -1073741819 (0xC0000005)"
another thing
how can i use overloading function in my code
[/#include<iostream>


using namespace std;

class matrix{
private:


int i,j;
int **p;

public:
int M,N;
matrix(){
p;
}
matrix(int M,int N):M(M),N(N){
p = new int *[M];
for (i=0;i<M;i++)
p[i] = new int [N];
}
void alloc (int i,int j, int a){
p[i][j] = a;
}
int read(int i,int j){
return p[i][j];
}
void setdata(int a){
for (i=0;i<M;i++){
for (j=0;j<N;j++){
p[i][j]= a;
}
}
}
void print(){
for (i=0;i<M;i++){
for (j=0;j<N;j++){
cout << p[i][j]<< " ";
}
cout<<endl;
}

}
~matrix(){
for (i=0;i<M;i++){
delete [] p[i];
}
delete [] p;
}
friend matrix sum(matrix &u,matrix &v);

};

int main(){
int M = 6;
int N = 6;
int a;
matrix p(M,N),q(M,N),p3(M,N),p4(M,N);
/*cout<< "enter value =";
cin>>a;

p.setdata(a);
q.setdata(2*a);
p.print();
cout<<endl;
q.print();
cout<<endl;
*/
for (int i=0;i<M;i++){
for (int j=0;j<N;j++){
p3.alloc(i,j,i+j);
}
}
p3.print();
cout<<endl;
p4 = sum(p3,p3);
p4.print();




}

matrix sum(matrix &u,matrix &v){
matrix w;
int M;
int N;
for (int i=0;i<M;i++){
for (int j=0;j<N;j++){
w.alloc(i,j,u.read(i,j) + v.read(i,j));
}
}
return w;
}

]
Last edited on
initialise your variables
where should i do that?
When you create them. That's what initialise means.
Last edited on
i didnt understand i create them
You are defining redundant Ms and Ns, and this is confusing you.

Your class already has M and N variables. So if you have an object of type matrix, then my_matrix.M and my_matrix.N exist.
1
2
3
4
int M;
int N;
for (int i=0;i<M;i++){
for (int j=0;j<N;j++){

M and N here are just local variables. They do NOT contain valid values, because you haven't given any value to them. Perhaps you want u.M or v.M.
Last edited on
i didnt understand i create them

Yes, I know. You asked when you should initialise them. I'm directly answering your question, by telling you that you should initialise them when you create them - indeed, that initialisation can only occur when you create them.

What aren't you understanding here?
read() is public. alloc() is public. There is no reason for sum to be a friend.

u is not modified within sum(). v is not modified within sum().
Yet, you don't promise that you won't change them and thus can't sum two constant matrices.

What should happen in:
1
2
3
matrix foo( 2, 3 );
matrix bar( 42, 7 );
matrix snafu = sum( foo, bar );


1
2
3
4
5
6
7
matrix sum(matrix &u,matrix &v){
  matrix w;
  // How many rows and columns does w have right now?

  w.alloc( 0, 0, 42 );
  // Why Application Error 0xc0000005 (Access Violation) here?
}
On that note, it's also just misleading that a function called "alloc" doesn't allocate memory.
allocating in 2-d is nothing but trouble.

did you know you can define operators in c++? Then p4 = p2+p3 becomes legal syntax.


you have some very subtle and annoying memory problems with your approach.
sum creates w.
sum destroys w when it ends. but it returned it as well.
the default assignment operator is going to copy the pointers, which were deleted, to p4 and then it will blow up.

I highly recommend that when you delete a pointer, you set it to null immediately.

I think you will have to make your own assignment operator, and due to that, follow rule of 3 etc as your program grows. If you keep to this approach. If you move to my recommended vector approach, you won't need all this memory juggling.

the quick fix for what you have is to make sum use a pointer instead.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
matrix* sum(matrix &u,matrix &v)
	{
		matrix *w = new matrix(u.M,u.N);		
		//w[0].name = "W";  //to find the bug I had each matrix tell me about its dtor activity by naming each object. 
		for (int i=0;i<u.M;i++)
		{
			for (int j=0;j<u.N;j++)
			{
				w[0].alloc(i,j,u.read(i,j) + v.read(i,j));				
			}
		}		
		return w;
	}


and down in main:
matrix *p5 = sum(p3,p3);
	p5[0].print();
	delete p5;


the above code fixes the crashes and works, but its not a clean fix, its a minimal change fix. It just prevents w's matrix object from being auto destroyed, forcing you to do that yourself down in main.

do you understand that w deleted its pointers, but p4 uses those pointers, and that goes all kinds of wrong? These objects CANNOT share pointers (cannot allow assignment operator to copy the pointers) because they destruct delete them. When a = b then a's p == b's p and whichever one dies first the other one is going to have problems after that.... !

classes with pointers (dynamic memory) cause nothing but trouble. I recommend a do-over with a 1-d vector for p, and the bulk of your problems will clear up quickly. Actually, pointers for dynamic memory are trouble, and best not to do that.
Last edited on
thank you very much jonnin
i understood very well but one question!
why when i eliminate two for in the sum function and just i put w=u it return u. why it dont destroy?
another thing

the destruction is property of the class or is because of destruction function?
U is a reference to P3. That was created and scoped in main, so it is destroyed when main ends, not sum. Sum destroys only what was created inside it, which was W. I you modify U, you also modified P3, though, which may be an unwanted side effect if not careful.

Yes, the destruction is defined by the class in the ~ function.
The ~ destruction function is created FOR you if you do not make your own, but the automatic one is not smart enough to destroy pointers, so you did the right thing by defining it. That is not the problem, the problem is that you did not make a safe copy operator so your assignments are doing something unwanted (copying pointers to another instance). You need to prevent that from happening, which is complicated -- you have to know if the target of the assignment has memory already, and if its the right size, and so on.

Which is what I was trying to say. Dynamic memory and classes takes a bit to get correct for all scenarios, its a difficult and high risk design.
I had to do this pre c++98 (write a linear algebra tool, it let us use most .m files as c++ with just a few easy changes). I minimized memory creation and destruction by pulling from a global pool of memory, and I computed all my results like your sum directly in that and handed out a pointer to that, solving the issue you are facing as well as the keeping the performance hits of new/delete cycles low. This took a ton of code to manage properly... there is no magic answer, but it did solve 2 problems at once (performance and the memory management issues you are seeing in your sum routine).
The tools we have now make these issues go away: you are doing it the older, harder way.
Last edited on
Topic archived. No new replies allowed.