Operator et pointeur [C++]
Résolu
Char Snipeur
Messages postés
9813
Date d'inscription
Statut
Contributeur
Dernière intervention
-
Benur29 -
Benur29 -
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
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
A voir également:
- Operator et pointeur [C++]
- Pointeur souris - Guide
- Curseur Windows 10 : comment bien voir la souris à l'écran - Guide
- Le pointeur de mon pc portable ne marche plus - Guide
- Operator openai - Accueil - Intelligence artificielle
- Pointeur laser publicitaire ✓ - Forum Loisirs / Divertissements
9 réponses
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+
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+
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
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
Matrix& operator*(matrix& A, Matrix& B)
l'opérateur * doit retourner *this et pas un objet temporaire alloué !
l'opérateur * doit retourner *this et pas un objet temporaire alloué !
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
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
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
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
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 .
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 .
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.
Tout à fait d'accord avec charsniper mais en fait c'est presque bon :
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 :
Bonne chance
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
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
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