-3

My code does not run correctly and I don't know how to fix it. This is not a duplicate question to someone asking what is the rule of three because that post does not help me in solving my question as in this post im using a pointer pointer array. I don't know what I did wrong in my big three functions but can someone please help me correct my mistake. The compiler is highlighting delete[] matrix[i]; in the the destructor when i=2 inside the for loop

In my header file I have:

#ifndef fasdf_dynn_h
#define fasdf_dynn_h

#include <iostream>
#include <fstream>
#include<string>
#include <cstdlib>
#include <vector>

using namespace std;
template <class T>

class MatrixdynVector{

public:
   // MatrixdynVector()
      {
        //creates a 3 by 3 matrix with elements equal to 0
        m=3;
        n=3;

        matrix=new int*[m];

      for(int i=0;i<m;i++)
         matrix[i]=new int[n];

    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
           matrix[i][j]=0;
      }
   // MatrixdynVector(int m,int n);

    template <class H>
    MatrixdynVector<H>(const MatrixdynVector<H>& c)//copy constructor
    {
        m=c.m;
        n=c.n;

        for (int i = 0; i < c.m; i++)
            for (int j = 0; j < c.n; j++)
                matrix[i][j] = c.matrix[i][j]; // add data to it
    }

    template <class H>
    MatrixdynVector<H>& operator =(const MatrixdynVector<H>& c)//asignment
    {
        if (this == &c)
        {
            return *this;
        }
        else
        {
            matrix = new int*[c.m];
            for (int i = 0; i < c.m; i++)
                matrix[i] = new int[c.n]; // create a multi dimensional array

            for (int i = 0; i < c.m; i++)
                for (int j = 0; j < c.n; j++)
                    matrix[i][j] = c.matrix[i][j]; // add data to it

            for (int i = 0; i < c.m; i++)
                delete[] matrix[i]; // delete the second dimension of the matrix

            delete[] matrix; // delete the first*/

            return *this;
        }
    }

    ~MatrixdynVector()
    {
        if(matrix!=NULL)
        {
            for (int i = 0; i < m; i++)
               delete[] matrix[i]; // delete the second dimension of the matrix

            delete[] matrix; // delete the first

            matrix=NULL;
        }
    }
private:
    int m,n;
    int** matrix;
};


#endif
Brogrammer
  • 191
  • 1
  • 1
  • 10
  • ***My code does not compile correctly*** Maybe you should edit the question to post the compiler errors. – drescherjm Jul 05 '15 at 16:03
  • @drescherjm I did but I'm afraid that someone might think this is a duplicate post because it relates to the big three but the original post doesnt help me with my issue. Anyways I have updated the title – Brogrammer Jul 05 '15 at 16:07
  • A runtime error is not a compiler error. – drescherjm Jul 05 '15 at 16:08
  • @drescherjm Ok im sorry what I meant to say that I get a runtime error that causes the program to set a breakpoint. Please help me – Brogrammer Jul 05 '15 at 16:09
  • Your copy constructor code is wrong. – drescherjm Jul 05 '15 at 16:10
  • In the constructor, you doesn't allocate the memory for your matrix. It seems new int[...] are missing. And in your operator= function, it's confusing : first, you doesn't change m and n variables (so you lost the size of your matrix) and in your code, you copy the matrix (with a good memory allocation in that case) but after that, you delete it. And you doesn't set matrix to NULL. So you're sure gonna have some troubles if you use these functions. – Sébastien Doncker Jul 05 '15 at 16:11
  • @drescherjm I KNEW IT but anyways shouldnt the copy constructor be similar to the assignment operator. With that logic in mind i just copied everything over without creating a new array. How do i fix it though? – Brogrammer Jul 05 '15 at 16:11
  • @SébastienDoncker How should I rewrite them. Should I have assignment of m=c.m and n=c.n in my assignment operator also? – Brogrammer Jul 05 '15 at 16:15
  • @DieterLücking is also correct. The functions in your template class should not be declared as template functions. – drescherjm Jul 05 '15 at 16:17
  • After you fix the problem @DieterLücking mentioned, why are you deleting the matrix after you create it and copy in `operator =`? – drescherjm Jul 05 '15 at 16:23
  • @drescherjm I thought I was deleting the old matrix that I used to assign into the new one. Anyways even if i dont delete them in my = operator i still get the same runtime error – Brogrammer Jul 05 '15 at 16:24
  • Oh, that delete needed to happen first. Not last. Make sure MatrixdynVector(); set matrix to nullptr and check for that. – drescherjm Jul 05 '15 at 16:25
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82413/discussion-between-guploo-and-drescherjm). – Brogrammer Jul 05 '15 at 16:27
  • See this question: '[1D or 2D array, what's faster?](http://stackoverflow.com/questions/17259877/1d-or-2d-array-whats-faster)' for some informaion on why you probably want to use a one-dimensional approach to store two-dimensional data instead. In my answer to the question I have a small example for a matrix class that makes use of `std::vector` internally and thus avoids copy constructor, copy assignment and destruction completely. – Pixelchemist Jul 05 '15 at 22:20

2 Answers2

1

A template is no copy constructor.

template <class H>
MatrixdynVector(const MatrixdynVector<H>&) // without <H>, which is an syntax error

You need

MatrixdynVector(const MatrixdynVector&)

Also: Properly pair new and delete (You have no new in the constructor).

0

I can't compile it to verify but I think you should have something like that:

EDIT: After compile it and chatting with question's author. Here isa working version.

#ifndef fasdf_dynn_h
#define fasdf_dynn_h

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

using namespace std;

template <class T>
class MatrixdynVector {
private:
    int m,n;
    T **matrix;

public:
    MatrixdynVector();
    MatrixdynVector(int m,int n);
    MatrixdynVector(T diagonal, int n, int m);
    MatrixdynVector(const MatrixdynVector<T>& c);//copy constructor
    virtual ~MatrixdynVector();

    MatrixdynVector<T>& operator =(const MatrixdynVector<T>& c); //assignment
    MatrixdynVector<T> operator -();

    friend ostream& operator <<(ostream& outs, const MatrixdynVector<T> &obj) {
        for (int i = 0; i < obj.m; i++) {
                for (int j = 0; j < obj.n; j++) {
                    outs << " "<< obj.matrix[i][j];
                }
                outs<<endl;
            }
            outs<<endl;

            return outs;
    }
    friend istream& operator >>(istream& in, MatrixdynVector<T> &obj) {
        for (int i = 0; i < obj.m; i++) {
            for (int j = 0; j < obj.n; j++) {
                //if (in==cin)
                    //cout <<"input elements for element at row:"<<i<<" column:"<<j<<": ";
                in >> obj.matrix[i][j];
            }
        }

        return in;
    }

    friend MatrixdynVector<T> operator *(const MatrixdynVector<T>& A, const MatrixdynVector<T>& B) {
        MatrixdynVector<T> product(A.m, A.n);

            for (int i=0;i<A.m; i++) {
                for (int j=0;j<A.n; j++) {
                    T sum=0;
                    for (int k=0; k<A.n; k++) {
                        sum = sum+A.matrix[i][k]*B.matrix[k][j];
                    }
                    product.matrix[i][j]=sum;
                }
            }

            return product;
    }
    friend MatrixdynVector<T> operator +(const MatrixdynVector<T>& a, const MatrixdynVector<T>& b) {
        MatrixdynVector<T> additon(a.m, a.n);   // you should initialize it with the good size.

            if((a.n != b.n) || (a.m != b.m)) {
                // here you should throw an error : the two matrixes should be the same size.
            }

            for(int i=0;i<a.m;i++) {
                for(int j=0;j<b.n;j++) {
                    additon.matrix[i][j] = a.matrix[i][j] + b.matrix[i][j];
                }
            }

            return additon;
    }
    friend MatrixdynVector<T> operator -(const MatrixdynVector<T>& A, const MatrixdynVector<T>& B) {
        MatrixdynVector<T> subtract(A.m, A.n);

        if( A.m!= B.m || A.n!= B.n) {//if they have different rows and columns then they cant be equal
            // throw an exception.
        }
        else {
            for(int i=0;i<A.m;i++) {
                for(int j=0;j<B.n;j++) {
                    subtract.matrix[i][j]=A.matrix[i][j]-B.matrix[i][j];
                }
            }
        }

        return subtract;

    }
    friend bool operator ==(const MatrixdynVector<T>& A,const MatrixdynVector<T>& B) {
        //if they have different rows and columns then they cant be equal
            if( A.m!= B.m || A.n!= B.n) {
                return false;
            }
            else {
                for(int i=0;i<A.m; i++) {
                    for(int j=0;j<B.n; j++) {
                        if(A.matrix[i][j] != B.matrix[i][j]) {
                            cout<<A.matrix[i][j]<< " does not equal "<<B.matrix[i][j]<<endl;
                            return false;
                        }
                    }
                }

                return true;
            }
    }
};


template <class T>
MatrixdynVector<T>::MatrixdynVector() {
    m=3;
    n=3;

    matrix=new T*[m];

    for(int i=0; i<m; i++) {
        matrix[i]=new T[n];
        for(int j=0;j<n;j++) {
            matrix[i][j]=0; // be careful! If T is not int, 0 can be bad initializer !!!
        }
    }
}

template <class T>
MatrixdynVector<T>::MatrixdynVector(int x,int y) {
    m = x;
    n = y;

    matrix=new T*[m];

    for(int i=0; i<m; i++) {
        matrix[i]=new T[n];
        for(int j=0;j<n;j++) {
            matrix[i][j]=0; // be careful! If T is not int, 0 can be bad initializer !!!
        }
    }
}

template <class T>
MatrixdynVector<T>::MatrixdynVector(T diagonal, int x, int y) {
    m=x;
    n=y;

    matrix=new T*[m];

    for(int i=0;i<m;i++) {
        matrix[i]=new T[n];
        for(int j=0;j<n;j++) {
            if(i==j) {
                matrix[i][j]=diagonal;
            }
            else {
                matrix[i][j]=0;// be careful! If T is not int, 0 can be bad initializer !!!
            }
        }
    }
}

template <class T>
MatrixdynVector<T>::MatrixdynVector(const MatrixdynVector<T>& c) {
    m=c.m;
    n=c.n;

    matrix = new T*[m];

    for (int i = 0; i < m; i++) {
        matrix[i] = new T[n];
        for (int j = 0; j < c.n; j++) {
            matrix[i][j] = c.matrix[i][j]; // add data to it
        }
    }
}

template <class T>
MatrixdynVector<T>::~MatrixdynVector() {
    if(matrix!=NULL) {
        for (int i = 0; i < m; i++) {
            delete[] matrix[i]; // delete the second dimension of the matrix
        }

        delete[] matrix; // delete the first

        matrix=NULL;
    }
}

template <class T>
MatrixdynVector<T>& MatrixdynVector<T>::operator =(const MatrixdynVector<T>& c) {
    if(this != &c) {
        if(matrix != NULL) {
            for (int i = 0; i < m; i++) {
                delete[] matrix[i]; // delete the second dimension of the matrix
            }
            delete[] matrix; // delete the first*/
        }

        m=c.m;
        n=c.n;

        matrix = new T*[c.m];

        for (int i = 0; i < c.m; i++) {
            matrix[i] = new T[c.n]; // create a multi dimensional array
            for (int j = 0; j < c.n; j++) {
                matrix[i][j] = c.matrix[i][j]; // add data to it
            }
        }
    }

    return *this;
}

template <class T>
MatrixdynVector<T> MatrixdynVector<T>::operator -() {
    MatrixdynVector<T> new_matrix(m, n);

    for(int i=0;i<m;i++) {
        for(int j=0;j<n;j++) {
            new_matrix.matrix[i][j]=-matrix[i][j];
        }
    }
    return new_matrix;
}

#endif