Operator et pointeur [C++]

Résolu/Fermé
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 - 3 mai 2004 à 17:31
 Benur29 - 26 janv. 2007 à 15:14
Bonjour, je fait une classe Matrix, defini comme ça :
struct Matrix{vector<double>M;}
pour définir l'opérateur multiplier :
Matrix& operator*(matrix& A, Matrix& B)
{matrix *tmp;
tmp=new matrix;
// calculs du produit que je vous épargne
return *tmp;}
voila l'algorithme de base. Le programme parfaitement, mise à par une ENORME fuite de mémoire qui est du au fait que tmp ne soit pas détruit à la fin de l'apel de la fonction.
Je ferai bien la declaration de tmp en non-pointeur, mais le compilateur me dit que je retourne un variable local. Et si j'enleve les "&" , le compilateur n'est pas content non plus, ou alors le programme plante pour violation d'acces.
Je sais que le problème n'est pas facile, mais la je seche...
Si quelqu'un pouvait m'aider, je lui en serai très reconnaisant.
Merci

Salutation !
Char Snipeur

9 réponses

blurk Messages postés 486 Date d'inscription vendredi 16 avril 2004 Statut Membre Dernière intervention 15 mars 2009 160
4 mai 2004 à 09:04
dans le constructeur de matrix, tu peux mettre un new, il y a même
moyen( de passer un paramètre pour la taille d'allocation lors de la déclaration d'une instance de matrix.
matrix(1) *a; avec un new dedans. (1 à multiplier par sizeof de matrix dans le constructeur)
et dans le destructeur le delete[]
Les constructeurs par défaut servent surtout à ça.

autrement, je sais qu'il n'est pas interdit de faire de l'allocation statique:
Matrix& operator*(matrix A[2], Matrix B[2] );
le compilateur se débrouille tout seul pour l'allocation.
Je sais pas si c'est la solution, mais il y a sûrement encore d'autres moyens.

a+
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
4 mai 2004 à 09:48
Merci de ta réponse blurk. Je n'ai pas tout compris surtout car j'ai toujours essayer d'éviter les new et delete. Je ne sais pas très bien comment ils fonctionnent... Je vais me renseigner.
en fait pour l'opérateur, les "&" dans l'apel, si je ne les met pas, j'ai des erreurs de calcul : le passage par valeur se fait rès mal. En plus il me parait un peu restrictif de donnée une taille de matrice dans l'appel "matrix A[2]" si je fait une matrice plus grande, je fait comment?

Salutation !
Char Snipeur
0
Matrix& operator*(matrix& A, Matrix& B)

l'opérateur * doit retourner *this et pas un objet temporaire alloué !
0
marvinrouge
26 mai 2004 à 17:06
oups désolé je viens de dire une grosse BETISE.
c'est la fatigue.
j'arretes de bosser, je rentre chez moi et je corrige ce code demain ...
0
marvinrouge
26 mai 2004 à 17:37
Je reviens après 10 cafés, ça va mieux

Conventions classiques C++
- l'opérateur * rend Matrice
- l'opérateur *= rend une Matrice*
-ils prennent tous les 2 un seul paramètre

donc
Matrice& operator*=(matrix& b)
{
return *this = *this * b; // ici il FAUT que l'opérateur = existe ET on se sert de l'opérateur * écrit ci dessous
}

Matrice operator*(matrix& b) {
Matrice c(this->getNbLigs(), this->getNbCols());
//remplissage de c
return c; // ici il FAUT que le constrcuteur de copie existe
}

tu dois définir aussi

Matrice& operator=(matrix& b) { // opérateur d'affetatiion
// ...
}

Matrice(matrix& b) { // constrcuteru de copie
// ...
}


est-ce clair ?

marvinrouge
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Bien que la discussion soit terminée depuis belle lurette, je la complète pour éclairer d'autres esprits

si on déclare ainsi alors on doit retourner *this :
Matrice& operator*=(matrix& b)
{
return *this = *this * b; // ici il FAUT que l'opérateur = existe ET on se sert de l'opérateur * écrit ci dessous
}


par contre si on déclare de la façon qui suit, on peut retourner une valeur construite dans la fonction membre :
Matrice& operator*=(matrix& b) const
{
Matrice* resultat = new Matrice(param_d-init-du_constructeur);
.....
return *resultat
}

En espérant vous éclairer
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
25 janv. 2007 à 08:54
Salut.
Après des tests, et vue que j'ai apris un peu mieux le C++.
Le mieux est d'utiliser :
Matrix operator*(Matrix& A, Matrix& B);
cette fonction est défini en dehors de la class, c'est une surcharge de l'opérateur binaire '*'
J'ai enlever le '&' dans le retour de la fonction, car c'est la valeur qui nous intéresse, il n'y a aucune utilité de modifier A*B (A*B=6 n'a pas de sens en affectation) J'ai mis des '&' dans les paramètres de la fonctions pour passer les références des objets, car cela évite les erreurs de recopie et gagne du temps de recopiage des objets.
daccord sur la fonction membre 'operator*=' elle est parfaite.
en revanche la fonction 'matrix& operator*(matrix& b)' génère toujours des fuites de mémoire car la matrice resultat n'est jamais détruite. Dans ce cas, il est possible (3 matrice A,B et C) de faire :
A*B=C, resultat prend la valeur de C par l'opérateur '=' mais A et B ne sont pas modifier. et à chaque fois que tu fera A*B tu créra une nouvelle variable resultat .
0
la solution :

matrix& operator*(matrix& b)const
{
matrix* result = new matrix(.......);

...........

return = *result;
}

mais bon fais comme tu le sens hein ..........lol

bon amusement
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
26 janv. 2007 à 09:31
Je maintient, ta solution n'es pas bonne car elle engendre une fuite de mémoire, et aussi pour les raisons exposés dans le messsage précédent.
0
mamiemando Messages postés 33073 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 avril 2024 7 748
26 janv. 2007 à 10:14
Tout à fait d'accord avec charsniper mais en fait c'est presque bon :
matrix operator*(matrix& b)const {
  matrix result(.......); 
   //...
  return result
}

En fait si tu calcule A*B tu es effectivement de créer une matrice C=A*B et donc de l'allouer (car tu ne veux modifier ni A, ni B). Cependant qui dit new dit delete, et ici le delete n'était jamais fait (donc la mémoire occupée par C jamais rendue).

Ici tu ne peux pas retourner une référence, ça n'a pas de sens. Retourner une référence n'a de sens que si c'est une variable qui est déjà créée. Typiquement quand tu passes une variable en paramètre, on passe en générale la référence car ça évite de recopier dans la pile la variable passée en paramètre. Ici tu es de toutes façons condamné à créer une nouvelle variable de retour C donc... on la retourne directement :)

Au niveau allocation c'est mieux, car la variable de retour sera déclarée sans new et sera donc automatiquement détruite à la fin du scope ou elle est déclarée :
matrix A,B;
//Initialisation de A et B
//...

// Calcul de C = A*B
{
  int x=69;
  matrix C = A*B;
   //...
} // C est détruite en arrivant à cette accolade au même titre que x

Bonne chance
0
ok ; autant pour moi

En ce ki concerne tes fuites memoire : je suppose que tu utilises des tableaux intermédiaires.

si tu les alloues dynamiquement : n'oublie pas de les détruire proprement :

int* tab = new int[n];
....
delete[] tab;


int** tab = new int*[n1]; //tab[n1][n2]
for(int j= 0; j<n1 ; j++)
{
tab[j] = new int[n2];
for(int h=0; h<n2 ; h++)
{
tab[j][h] = .........;
}
}
......
for(j= 0; j<n1 ; j++)
{
delete[] tab[j];
}

delete[] tab;

avec ça c propre
0