2013-07-24 1 views
0

J'ai une classe appelée Matrix avec 2 dimensions pointeur bool ** matrix.pourquoi l'opérateur d'appel d'appel déclenche la fonction de destruction?

oeil à ce code:

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

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

    //return *this; 
} 

J'ai appelé mon opérateur = dans ma fonction principale comme ceci:

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; 

Le desctructor est comme ceci:

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; 
} 

Quand je exécuter mon programme en xcode je reçois:

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 

et il est l'air bien, mais quand je change la fonction = opérateur comme ceci:

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

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

    return *this; 
} 

Je reçois cela comme résultat:

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 

quelqu'un peut me expliquer pourquoi le destructor déclenche plus tôt dans le dernier code?! et comment puis-je empêcher

vous remercie à l'avance

+0

Pouvez-vous poster votre déclaration pour votre classe et aussi le code qui remplit (initialise) votre objet? –

+1

Conseil rapide: jetez tout cela et écrivez un simple wrapper autour de 'std :: vector'. Ecrire le tout sera probablement moins de travail que de réparer ce que vous avez maintenant. –

+0

La réponse de Mark B est correcte, mais si vous obtenez cette erreur, vous avez d'autres problèmes, très probablement dans votre constructeur de copie, que je suppose que vous n'avez pas réussi à écrire. –

Répondre

3

Votre opérateur d'affectation renvoie *this en valeur, en en faisant une copie. Normalement, vous reviendriez une référence:

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

La copie est faite en utilisant le constructeur de copie implicite, qui copie simplement le pointeur de membre. Vous avez maintenant deux objets qui tous les deux pensent qu'ils "possèdent" la mémoire allouée. La valeur temporaire renvoyée par operator= est rapidement détruite, supprimant la mémoire et laissant y avec un pointeur qui pend; vous obtenez l'erreur lorsque y essaie de supprimer la même mémoire une deuxième fois.

C'est pourquoi les classes qui gèrent les ressources doivent suivre le Rule of Three, afin de garantir leur sécurité de copie. Les conteneurs standard tels que std::vector le font; C'est généralement une bonne idée de les utiliser plutôt que de gérer vous-même la mémoire.

7

La raison en est que votre opérateur d'affectation de copie modifiée retourne en valeur qui crée une copie de la matrice, retourne, puis détruit.

La signature canonique pour votre opérateur d'affectation de copie est Matrix& Matrix::operator=(const Matrix& A) (notez que je renvoie par référence non-const).

EDIT: Gardez à l'esprit que si vous utilisez simplement vector, toute cette gestion de mémoire disparaît et toutes ces fonctions peuvent utiliser les valeurs par défaut du compilateur. Bien que si vous stockez en fait bool dans la matrice, vector<bool> est spécialisé et vous devez juste vous assurer que vous comprenez comment cette spécialisation interagit avec votre code.

+0

Il semble également qu'il utilise le constructeur de copie par défaut, qui copie la valeur du pointeur, plutôt que de faire une copie des données. –

+0

Merci pour votre réponse rapide, et vous avez raison, je change la fonction = opérateur pour retourner la référence, et cela fonctionne comme un charme. une dernière question: je vais utiliser et compiler ce code sur d'autres OS comme Windows ou Linux. est la norme de classe de vecteur dans d'autres compilateurs? – Shnd

Questions connexes