Search code examples
c++destructorequals-operator

why calling assignment operator triggers destruction function?


I have a class called Matrix with 2 dimensional pointer bool** matrix.

look at this code :

void Matrix::operator=(const Matrix& A){ 

    cout << "address in A : " << A.matrix << endl ;
    cout << "address in y : " << matrix << endl ;

    //return *this;
}

I called my = operator in my main function like this :

Matrix x(3,5);
Matrix y(3,5);

x.set(1,4,1);
cout << "address out X: " << x.matrix << endl;
cout << "address out Y: " << y.matrix << endl;
y = x;
cout << "address out X: " << x.matrix << endl;
cout << "address out Y: " << y.matrix << endl;

The desctructor is like this :

Matrix::~Matrix(){
    cout << "address de : " << matrix <<endl;
    for (int i=0;i<m;i++)
        delete[] matrix[i];
    delete[] matrix;
    cout << "address de finish : " << matrix <<endl;
}

When I run my program in xcode i get :

address out X: 0x100103ab0
address out Y: 0x100103af0
address in A : 0x100103ab0
address in y : 0x100103af0
address out X: 0x100103ab0
address out Y: 0x100103af0
address de : 0x100103af0
address de finish : 0x100103af0
address de : 0x100103ab0
address de finish : 0x100103ab0

and it's look fine but when i change the = operator function like this :

Matrix Matrix::operator=(const Matrix& A){

    cout << "address in A : " << A.matrix << endl ;
    cout << "address in y : " << matrix << endl ;

    return *this;
}

I get this as result :

address out X: 0x100103ab0
address out Y: 0x100103af0
address in A : 0x100103ab0
address in y : 0x100103af0
address de : 0x100103af0
address de finish : 0x100103af0
address out X: 0x100103ab0
address out Y: 0x100103af0
address de : 0x100103af0
Thesis(26190) malloc: *** error for object 0x100103b10: pointer being freed was not allocated

can anyone explain to me why the destructor triggers sooner in the latter code ?! and how can i prevent it

thank you in advance


Solution

  • Your assignment operator is returning *this by value, making a copy of it. Normally, you would return a reference:

    Matrix& Matrix::operator=(const Matrix& A)
    //    ^
    

    The copy is made using the implicit copy constructor, which simply copies the member pointer. You now have two objects which both think they "own" the allocated memory. The temporary value returned by operator= is soon destroyed, deleting the memory, and leaving y with a dangling pointer; you get the error when y tries to delete the same memory a second time.

    This is why classes that manage resources should follow the Rule of Three, to ensure that they are safe to copy. Standard containers such as std::vector do this; it's usually a good idea to use these rather than managing memory yourself.