OVH Cloud OVH Cloud

Probleme de comprehension : constructeur de copie (templates?)

53 réponses
Avatar
Alex Paris
Bonjour =E0 tous !

Voil=E0 mon petit exemple que je compile en utilisant g++ (cygwin)


#include <iostream>

using namespace std;

template<class T>
class Matrix
{
public:
Matrix(int size);
Matrix(const Matrix<T> &copy);

~Matrix();

Matrix<T>& operator=3D(const Matrix<T>& matrix);

Matrix<T> operator+(const Matrix<T>& second);

private:
int _size;
};

template <class T>
Matrix<T>::Matrix(int size)
: _size(size)
{
cout << "--- Constructor called --- " << endl;
}

template <class T>
Matrix<T>::Matrix(const Matrix<T> &copy)
: _size(copy._size)
{
cout << "--- Copy constructor called --- " << endl;
}

template <class T>
Matrix<T>::~Matrix()
{
cout << "--- Destructor called --- " << endl;
}

template <class T>
Matrix<T>& Matrix<T>::operator=3D(const Matrix<T>& matrix)
{
cout << "--- Operator \"=3D\" called --- " << endl;
_size =3D matrix._size;
}

template <class T>
Matrix<T> Matrix<T>::operator+(const Matrix<T>& second)
{
cout << "--- Operator \"+\" called --- " << endl;
Matrix<T> result(_size);
return result;
}



int main()
{
cout << "Declaration m1" << endl;
Matrix<int> m1(2);
cout << "Declaration m1" << endl;
Matrix<int> m2(2);

cout << "Declaration mSum1" << endl;
Matrix<int> mSum1(2);
cout << "mSum1 =3D m1 + m2" << endl;
mSum1 =3D m1 + m2;

cout << "Declaration mSum2 =3D m1 + m2" << endl;
Matrix<int> mSum2 =3D m1 + m2;

cout << "Declaration mSum3" << endl;
Matrix<int> mSum3(2);
mSum3 =3D m1 + m2;

cout << "Declaration m4 =3D mSum3" << endl;
Matrix<int> m4 =3D mSum3;

int ret;
cin >> ret;

return ret;
}


Comme on voit bien dans le programme en bas la cr=E9ation est appell=E9e
plusieurs fois.

Et voil=E0 la sortie du programme :

$ ./a.exe
Declaration m1
--- Constructor called ---
Declaration m1
--- Constructor called ---
Declaration mSum1
--- Constructor called ---
mSum1 =3D m1 + m2
--- Operator "+" called ---
--- Constructor called ---
--- Operator "=3D" called ---
--- Destructor called ---
Declaration mSum2 =3D m1 + m2
--- Operator "+" called ---
--- Constructor called ---
Declaration mSum3
--- Constructor called ---
--- Operator "+" called ---
--- Constructor called ---
--- Operator "=3D" called ---
--- Destructor called ---
Declaration m4 =3D mSum3
--- Copy constructor called ---
0
--- Destructor called ---
--- Destructor called ---
--- Destructor called ---
--- Destructor called ---
--- Destructor called ---
--- Destructor called ---


Ce que m'int=E9resse le plus c'est pourquoi j'ai ces lignes l=E0 :
Declaration mSum2 =3D m1 + m2
--- Operator "+" called ---
--- Constructor called ---

Je ne vois pas l'operator=3D ni de constructeur de copie. Si je mets le
vrai code pour la classe matrix, le mSum2 est en effet la somme des 2,
l'objet est cr=E9=E9 et vit bien =E7a vie...

Quelqu'un saurait-il m'expliquer la suite des appels ici ? J'imagine
que la ligne
--- Constructor called ---
correspond =E0 la cr=E9ation de l'objet temporaire dans l'operator +. Mais
o=F9 est la trace de l'operator =3D ?



Merci d'avance
A+

10 réponses

1 2 3 4 5
Avatar
Christophe Lephay
"Alex Paris" a écrit dans le message de news:

1. Il faut que tu implémentes une classe qui va te SERVIR pour la
gestion de matrices... analyse algèbre matricielle etc etc....
2. Il faut écrire une classe Matrix , template, avec un constructeur
de copie, destructor et opérateur =, implémenter les opérations de +,
- et * pour cette classe et montrer son utilisation pour le int !
(cours d'informatique à l'école)

Alors on peut avoir des longs débats sur comment rendre les matrices
etc super performantes et tout et tout... tandis que le problème n'est
pas là : ) C'est pour avoir la NOTE !


La problématique est la même : pour augmenter tes chances d'avoir une bonne
note, il faut limiter le risque de faire des erreurs.

Du coup, tu aurais plutot interet à utiliser vector< vector< int > > plutot
qu'un int **.

Le problème éventuel, c'est si ton prof a jamais entendu parler de vector et
s'offusque s'il te voit utiliser des trucs dont il ignore tout.

Avatar
Michael DOUBEZ
On Wed, 08 Aug 2007 12:14:53 +0200, Michel Decima
:

Et puisqu'on est dans un cadre scolaire, montrer qu'on connait ces
techniques devrait permettre d'obtenir une meilleure note...


Encore faut-il que le prof soit suffisamment ouvert, et ça, c'est pas
forcément gagné.
Le premier rôle d'un élève est un travail de psychologie : comprendre
ce que le professeur veut.


Ce qui suppose qu'il ait compris le cours donc on pourrait dire que
l'aspect psy n'est que le deuxième rôle.

D'autre part, je ne pense pas qu'en faire plus marque des points à moins
que ce ne soit à propos. Le mieux est l'ennemi du bien.

Michael


Avatar
Michael DOUBEZ
"Alex Paris" a écrit dans le message de news:

1. Il faut que tu implémentes une classe qui va te SERVIR pour la
gestion de matrices... analyse algèbre matricielle etc etc....
2. Il faut écrire une classe Matrix , template, avec un constructeur
de copie, destructor et opérateur =, implémenter les opérations de +,
- et * pour cette classe et montrer son utilisation pour le int !
(cours d'informatique à l'école)

Alors on peut avoir des longs débats sur comment rendre les matrices
etc super performantes et tout et tout... tandis que le problème n'est
pas là : ) C'est pour avoir la NOTE !


La problématique est la même : pour augmenter tes chances d'avoir une bonne
note, il faut limiter le risque de faire des erreurs.

Du coup, tu aurais plutot interet à utiliser vector< vector< int > > plutot
qu'un int **.


Un vector de vector est la meilleur façon de tout planter.
Par exemple si un vecteur s'amuse à lancer une exception pendant un
changement de taille, je ne te parle pas de l'état de la matrice.


Le problème éventuel, c'est si ton prof a jamais entendu parler de vector et
s'offusque s'il te voit utiliser des trucs dont il ignore tout.


Tout depends de l'intitulé du sujet. Si c'est un exercice de C++, ça
m'étonnerais qu'on lui reproche d'utiliser vector.

La méthode classique pour la représentation d'une matrice dense sans
autres caractéristiques (triangulaire, diagonale, creuse ...) est
d'utiliser un tableau unidimensionnel et d'utiliser operator()(int i,
int j){return (i*N+j);} pour acceder aux éléments.

A moins que ce ne soit demander (ou que le prof demande l'utilisation de
POD comme un tableau de valeurs), l'operateur de recopie n'est pas
nécessaire car tout est géré par le compilateur. Et c'est bien de
montrer qu'on sait ça aussi.

Finalement, les opérateurs algébriques ont intérêt à être définis en
dehors de la classe.

Michael


Avatar
Fabien LE LEZ
On Wed, 08 Aug 2007 13:27:52 +0200, Michael DOUBEZ
:

Un vector de vector est la meilleur façon de tout planter.
Par exemple si un vecteur s'amuse à lancer une exception pendant un
changement de taille, je ne te parle pas de l'état de la matrice.


J'ose espérer que c'est du second degré.

(Pour ceux qui n'auraient pas compris : si un bug dans ton programme
fait que vector lance une exception, le même bug aurait des
conséquences bien plus graves (corruption de la mémoire, plantages
aléatoires, etc.) avec un int**.
Je te dis pas l'état de la matrice si une exception est lancée dans la
deuxième ligne d'un code du style
delete[] data;
data= new int [...];
)

Note par ailleurs qu'il est relativement facile, avec vector<>::swap()
par exemple, de rendre la classe "strongly exception-safe" (i.e. en
cas d'exception, l'objet est dans le même état qu'avant l'appel à la
fonction).

Avatar
Christophe Lephay
"Michael DOUBEZ" a écrit dans le message de news:
46b9a704$0$14585$
Un vector de vector est la meilleur façon de tout planter.
Par exemple si un vecteur s'amuse à lancer une exception pendant un
changement de taille, je ne te parle pas de l'état de la matrice.


cf la réponse de fabien.

Le problème éventuel, c'est si ton prof a jamais entendu parler de vector
et s'offusque s'il te voit utiliser des trucs dont il ignore tout.


Tout depends de l'intitulé du sujet. Si c'est un exercice de C++, ça
m'étonnerais qu'on lui reproche d'utiliser vector.


De mon coté, je n'en serais pas surpris. Le C++ et le C++ enseigné par
certains professeur n'ont parfois que le nom en commun. J'ai déjà rencontré
des profs d'info enseignant le C++ qui n'avaient jamais entendu parlé de
vector (c'était il y a à peu pret 5 ans, les vector n'étaient donc pas une
nouveauté). Dans la foulée, les profs qui ne maitrisent pas leur sujet sont
souvent réfractaires aux notions qu'ils ne connaissent pas, impossible
qu'ils sont d'accepter l'idée qu'un de leur étudiants puisse connaitre
quelque chose qu'eux-mêmes ignorent.

Il y a deux mois, j'ai rencontré un autre prof qui affirmait qu'il était
impératif que toutes les déclarations de variables locales soient faites en
début de fonction.

En clair, tout ne dépend pas de l'intitulé du sujet, on en revient un peu à
la psychologie du prof dont parlait fabien (même s'il en parlait dans un
sens un peu différent).

La méthode classique pour la représentation d'une matrice dense sans
autres caractéristiques (triangulaire, diagonale, creuse ...) est
d'utiliser un tableau unidimensionnel et d'utiliser operator()(int i, int
j){return (i*N+j);} pour acceder aux éléments.


Ta méthode classique est nickel à supposé que la taille des matrices soient
fixe, ce qui est peu probable si on écrit un opérateur d'affectation.

A moins que ce ne soit demander (ou que le prof demande l'utilisation de
POD comme un tableau de valeurs), l'operateur de recopie n'est pas
nécessaire car tout est géré par le compilateur. Et c'est bien de montrer
qu'on sait ça aussi.


L'opérateur de recopie n'est sans doute pas nécessaire si tu utilises un
conteneur standard, mais j'aurais plutôt l'a priori contraire en utilisant
ta méthode classique.

Finalement, les opérateurs algébriques ont intérêt à être définis en
dehors de la classe.


Peut-être pour certains d'entre eux, mais tu parles de quel intéret,
concrètement ?

Pour la plupart d'entre eux, je serais tenté de dire que c'est plutôt
indifférent, plus une question de style que de réel intéret.


Avatar
Fabien LE LEZ
On Wed, 8 Aug 2007 14:11:14 +0200, "Christophe Lephay"
:

Le C++ et le C++ enseigné par
certains professeur n'ont parfois que le nom en commun.


Je crois bien que l'enseignement est un des domaines où l'hérédité du
C fait le plus de mal au C++.

(Et puis, bien évidemment, la pléthore de paradigmes acceptés par le
C++, si elle est une aubaine pour le programmeur sérieux, est aussi un
encouragement à faire n'importe quoi :-( )

Accessoirement, on peut se demander s'il est raisonnable d'enseigner
le C++ à l'école. De toutes façons, même un prof compétent a trop peu
d'heures de cours pour donner autre chose qu'une introduction.

Avatar
Christophe Lephay
"Fabien LE LEZ" a écrit dans le message de news:

Je crois bien que l'enseignement est un des domaines où l'hérédité du
C fait le plus de mal au C++.


J'ai fait exactement le même constat. Pour beaucoup, les profs ont appris le
C et c'est toujours le C qu'ils enseignent. La partie C++ de leur programme,
c'est une adaptation forcée qui se limite surtout à l'utilisation des
classes fournies par l'éditeur pour gérer l'interface graphique (microsoft,
en l'occurrence).

Avatar
Michael DOUBEZ
On Wed, 08 Aug 2007 13:27:52 +0200, Michael DOUBEZ
:

Un vector de vector est la meilleur façon de tout planter.
Par exemple si un vecteur s'amuse à lancer une exception pendant un
changement de taille, je ne te parle pas de l'état de la matrice.


J'ose espérer que c'est du second degré.

(Pour ceux qui n'auraient pas compris : si un bug dans ton programme
fait que vector lance une exception, le même bug aurait des
conséquences bien plus graves (corruption de la mémoire, plantages
aléatoires, etc.) avec un int**.
Je te dis pas l'état de la matrice si une exception est lancée dans la
deuxième ligne d'un code du style
delete[] data;
data= new int [...];
)


Avec un copy-before-release, je vois pas le problème. Mais je ne le
ferais pas.

Mon propos etait qu'un simple vector est mieux qu'un vector de vector.
Le redimensionnement d'une matrice représentée par un vector de vector
impliquerait de redimensionner chaque ligne ce qui est assez laid de
tous les points de vue. Bon, mon exemple de matrice avec des lignes de
différentes tailles en case d'exception n'est ni explicite, ni
pertinent, c'est vrai.

Michael


Avatar
Alex Paris
On 8 août, 12:14, Michel Decima wrote:

On Wed, 08 Aug 2007 03:01:58 -0700, Alex Paris :

Alors on peut avoir des longs débats sur comment rendre les matrices
etc super performantes


Il ne s'agit pas de ça, mais plutôt d'utiliser dès le début des
techniques simples permettant de faire un programme qui fonctionne du
premier coup.


Et puisqu'on est dans un cadre scolaire, montrer qu'on connait ces
techniques devrait permettre d'obtenir une meilleure note...


ET NON, mais pas du tout !

Alors on peut trouver une classe toute faite sur le net et dire voilà
la matrice ! Pas ça le but de l'exercice.
La personne n'est pas censé savoir quoi que ce soit sur la STL, et
d'ailleurs ne sait pas grande chose en informatique en général



Avatar
Alex Paris
On 8 août, 12:58, "Christophe Lephay"
wrote:
La problématique est la même : pour augmenter tes chances d'avoir une bonne
note, il faut limiter le risque de faire des erreurs.

Du coup, tu aurais plutot interet à utiliser vector< vector< int > > pl utot
qu'un int **.

Le problème éventuel, c'est si ton prof a jamais entendu parler de ve ctor et
s'offusque s'il te voit utiliser des trucs dont il ignore tout.


MAIS NON !!! C'est complétement à l'envers !

Imagine tu es un (une) étudiant(e) de médecine et tu NE SAIS
strictement RIEN sur l'informatique.

Tu utilises STL en disant - voilà fastoche ! Tu n'as pas assisté aux
cours tu arrives à la fin du trimestre et dit que tu sais tout faire.
C'est vite vérifié... Faut pas etre idiot pour comprendre que c'est
pas toi qui as fait le programme

Au contraire si l'exercice est bien défini tu as exactement ce que tu
as à faire, tu le fais puisque c'est prescrit et voilà. Rien à
reprocher.

Le but ce n'est pas d'obtenir le produit de matrices via un programme.
Mais l'exercice-même , n'est-ce pas ?

1 2 3 4 5