[C++] Amusons-nous avec le C++
2 participants
Page 1 sur 1
[C++] Amusons-nous avec le C++
Bien le bonjour !
Je ne sais pas s'il y a beaucoup d'adeptes du c++ par ici, mais j'ai décidé d'ouvrir ce topic pour montrer diverses bizarreries que l'on peut faire en c++.
Je tiendrai en historique les bizarreries dans ce premier post.
Je vous propose de vous poster des questions pour vous faire un peu chercher, et je posterai une explication plus tard.
Bizarrerie #1 Le message fantôme (difficulté: débutant)
Bizarrerie #2 Utilisation de l'opérateur virgule ! (difficulté: moyenne)
Bizarrerie #3 Surcharger l'opérateur virgule !!! (difficulté: expert)
Je ne sais pas s'il y a beaucoup d'adeptes du c++ par ici, mais j'ai décidé d'ouvrir ce topic pour montrer diverses bizarreries que l'on peut faire en c++.
Je tiendrai en historique les bizarreries dans ce premier post.
Je vous propose de vous poster des questions pour vous faire un peu chercher, et je posterai une explication plus tard.
Bizarrerie #1 Le message fantôme (difficulté: débutant)
Bizarrerie #2 Utilisation de l'opérateur virgule ! (difficulté: moyenne)
Bizarrerie #3 Surcharger l'opérateur virgule !!! (difficulté: expert)
Dernière édition par Duche le Ven 19 Déc 2008 - 20:38, édité 6 fois
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Bizarrerie #1 le message fantôme (difficulté: débutant)
Pour les Windowsiens, le code suivant est à exécuter en console, afin d'éviter que le programme ne s'ouvre et ne se referme immédiatement après avoir fini de s'exécuter (sinon vous ne pourrez pas voir l'effet
désiré)
De façon très étrange on peut constater que du texte s'affiche, alors que le main ne fait rien.
Pourquoi ?
Réponse:
En réalité, le main est une fonction comme toutes les autres, mais qui sera appelée par l'OS. Dans ce cas ci, la déclaration MonObjet o; déclare une variable globale, qui est donc accessible à partir de toutes les fonction. Mais je me suis amusé à afficher du texte dans le constructeur et le destructeur de mon objet.
Etant une variable globale, mon objet est initialisé AVANT l'appel à la fonction main, et détruit APRES être sorti de la fonction main. Le constructeur est donc appelé AVANT le main, et le destructeur APRES le main. Le main quant à lui, ne fait rien.
Pour les Windowsiens, le code suivant est à exécuter en console, afin d'éviter que le programme ne s'ouvre et ne se referme immédiatement après avoir fini de s'exécuter (sinon vous ne pourrez pas voir l'effet
désiré)
- Code:
#include
using namespace std;
class MonObjet
{
public:
MonObjet()
{
cout << "Je suis un message fantome !" << endl;
}
~MonObjet()
{
cout << "Moi aussi..." << endl;
}
};
MonObjet o;
int main (int argc, char** argv)
{
return 0;
}
De façon très étrange on peut constater que du texte s'affiche, alors que le main ne fait rien.
Pourquoi ?
Réponse:
En réalité, le main est une fonction comme toutes les autres, mais qui sera appelée par l'OS. Dans ce cas ci, la déclaration MonObjet o; déclare une variable globale, qui est donc accessible à partir de toutes les fonction. Mais je me suis amusé à afficher du texte dans le constructeur et le destructeur de mon objet.
Etant une variable globale, mon objet est initialisé AVANT l'appel à la fonction main, et détruit APRES être sorti de la fonction main. Le constructeur est donc appelé AVANT le main, et le destructeur APRES le main. Le main quant à lui, ne fait rien.
Dernière édition par Duche le Jeu 18 Déc 2008 - 20:07, édité 4 fois
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
En principe, il faudrait que MonObjet o; soit dans le main. S'il n'y a pas de main, le compilateur n'est pas content.
Mais s'il y a un main et que celui-ci est vide mais qu'il y a une classe (avec un constructeur et un destructeur), s'il y a un appel à cette classe en dehors du main, le main le prend quand-même en compte et l'exécute ?
Mais s'il y a un main et que celui-ci est vide mais qu'il y a une classe (avec un constructeur et un destructeur), s'il y a un appel à cette classe en dehors du main, le main le prend quand-même en compte et l'exécute ?
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Non, en réalité, le main est une fonction comme toutes les autres, mais qui sera appelée par l'OS. Dans ce cas ci, la déclaration MonObjet o; déclare une variable globale, qui est donc accessible à partir de toutes les fonctions. Mais je me suis amusé à afficher du texte dans le constructeur et le destructeur de mon objet.
Etant une variable globale, mon objet est initialisé AVANT l'appel à la fonction main, et détruit APRES être sorti de la fonction main. Le constructeur est donc appelé AVANT le main, et le destructeur APRES le main. Le main quant à lui, ne fait rien.
Etant une variable globale, mon objet est initialisé AVANT l'appel à la fonction main, et détruit APRES être sorti de la fonction main. Le constructeur est donc appelé AVANT le main, et le destructeur APRES le main. Le main quant à lui, ne fait rien.
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
OK ok. Sinon, en général, il ne faut rien mettre dans un constructeur/destructeur...
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Bien sur qu'il faut mettre des trucs dans les constructeurs et destructeurs !!!
Qu'est-ce que tu entends par là ?
Qu'est-ce que tu entends par là ?
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Ben on nous a dit d'éviter de mettre quoi que ce soit dans le constructeur et de préférer utiliser une méthode pour afficher du texte par exemple.
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Ha oui, il ne vaut mieux pas faire afficher du texte avec un constructeur ou un destructeur, mis à part pour le débug.
Mais sinon, ce ne sont pas du tout des fonctions qui ne servent à rien !!!
Mais sinon, ce ne sont pas du tout des fonctions qui ne servent à rien !!!
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Oui oui bien sûr qu'ils sont nécessaires !
Une autre bizarrerie ! Une autre bizarrerie ! ^^
Une autre bizarrerie ! Une autre bizarrerie ! ^^
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Bizarrerie #2Utilisation de l'opérateur virgule ! (difficulté: moyenne)
Voici un petit exemple d'utilisation de l'opérateur auquel on penserait le moins: l'opérateur virgule !
Si ça se trouve, vous ne saviez même pas qu'il existait... Que fait donc l'opérateur virgule ?
En réalité, il sépare des expressions un petit peu comme le point-virgule sépare des instructions, mais considère la suite d'expressions comme une seule expression, et renvoie le type de la dernière (de gauche à droite).
Petit programme exemple:
Que s'est-il passé réellement ?
Vous devez savoir qu'une variable toute seule est une expression à part entière, qui ne fait pas grand chose certes, mais c'est une expression valide. Lorsque le programme entrera dans les parenthèses, il effectuera d'abord l'expression a ensuite l'expression b et renverra la valeur de la dernière, à savoir la valeur de b qui sera alors copiée dans la variable c.
Si je ne mets pas les parenthèses:
Pourquoi ?
Réponse:
Cela vient du fait que pour le compilateur, c = a,b; est équivalent à (c = a),b;
Au même titre que tous les opérateurs, l'opérateur = et l'opérateur , ont des priorité différentes, l'opérateur = a une priorité plus grande.
Voyons quelques exemples de ce que permet l'opérateur virgule.
L'utilisation la plus courante réside dans les déclarations. Par exemple:
Ou encore:
Voici aussi une petite subtilité du for :
Prochain épisode: comment surcharger l'opérateur virgule
Voici un petit exemple d'utilisation de l'opérateur auquel on penserait le moins: l'opérateur virgule !
Si ça se trouve, vous ne saviez même pas qu'il existait... Que fait donc l'opérateur virgule ?
En réalité, il sépare des expressions un petit peu comme le point-virgule sépare des instructions, mais considère la suite d'expressions comme une seule expression, et renvoie le type de la dernière (de gauche à droite).
Petit programme exemple:
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
int a = 5;
int b = 8;
int c;
c = (a,b);
cout << "c = " << c << endl;
return 0;
}
Que s'est-il passé réellement ?
Vous devez savoir qu'une variable toute seule est une expression à part entière, qui ne fait pas grand chose certes, mais c'est une expression valide. Lorsque le programme entrera dans les parenthèses, il effectuera d'abord l'expression a ensuite l'expression b et renverra la valeur de la dernière, à savoir la valeur de b qui sera alors copiée dans la variable c.
Si je ne mets pas les parenthèses:
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
int a = 5;
int b = 8;
int c;
c = a,b;
cout << "c = " << c << endl;
return 0;
}
Pourquoi ?
Réponse:
Cela vient du fait que pour le compilateur, c = a,b; est équivalent à (c = a),b;
Au même titre que tous les opérateurs, l'opérateur = et l'opérateur , ont des priorité différentes, l'opérateur = a une priorité plus grande.
Voyons quelques exemples de ce que permet l'opérateur virgule.
L'utilisation la plus courante réside dans les déclarations. Par exemple:
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
int a,b,c;
a = 1;
b = 2;
c = 3;
cout << a+b+c << endl;
return 0;
}
Ou encore:
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
int a = 1,b = 2,c = 3;
cout << a+b+c << endl;
return 0;
}
Voici aussi une petite subtilité du for :
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
for(int i=0,k=0;i<10;i++)
for(int j=0;j<10;j++,k++)
cout << k << endl;
return 0;
}
Prochain épisode: comment surcharger l'opérateur virgule
Dernière édition par Duche le Ven 19 Déc 2008 - 19:29, édité 2 fois
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Ca doit venir du fait que pour le compilateur, c = a,b; est équivalent à (c = a),b;, non ?
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Tout à fait, au même titre que tous les opérateurs, l'opérateur = et l'opérateur , ont des priorité différentes, l'opérateur = a une priorité plus grande.
Voyons quelques exemples de ce que permet l'opérateur virgule.
L'utilisation la plus courante réside dans les déclarations. Par exemple:
Ou encore:
Voici aussi une petite subtilité du for :
Prochain épisode: comment surdéfinir l'opérateur virgule
Voyons quelques exemples de ce que permet l'opérateur virgule.
L'utilisation la plus courante réside dans les déclarations. Par exemple:
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
int a,b,c;
a = 1;
b = 2;
c = 3;
cout << a+b+c << endl;
return 0;
}
Ou encore:
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
int a = 1,b = 2,c = 3;
cout << a+b+c << endl;
return 0;
}
Voici aussi une petite subtilité du for :
- Code:
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
for(int i=0,k=0;i<10;i++)
for(int j=0;j<10;j++,k++)
cout << k << endl;
return 0;
}
Prochain épisode: comment surdéfinir l'opérateur virgule
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Bizarrerie #3 Surcharger l'opérateur virgule !!! (difficulté: expert)
(Ne pas confondre surcharge et surdéfinition (je l'ai fais moi-même en annonçant ce post). La surdéfinition consiste à refaire l'implémentation d'un opérateur dans une classé héritée (donc fonctionnement différent que dans la classe parent) et la surcharge consiste à utiliser le même opérateur pour des types différents (on parle alors de polymorphisme).)
Déjà qu'on l'utilise pas souvent cet opérateur virgule, on voudrait en plus le surcharger ? O__o Mais qu'est-ce que c'est que cette idée tordue ?
Oui ben c'est pas une bizarrerie pour rien non plus
Nous allons donc surcharger l'opérateur virgule dans un exemple. Cet opérateur a besoin de deux arguments et renvoie qqch si on le désire. On dit que c'est un opérateur binaire. Comme dans n'importe quelle surcharge, on peut choisir les types nécessaires et qui seront renvoyé, et là c'est au programmeur d'avoir des super idées (l'idée de cet exemple n'est pas de moi, je l'ai trouvée sur un site de programmation (je ne sais plus lequel)).
Imaginons que nous ayons une classe qui représente un vecteur, codée de façon tout à fait naturelle en C++ bien propre. Cela donne quelque chose comme:
On peut alors utiliser nos vecteurs de la façon suivante, par exemple
Jusque là tout va bien, notre classe est bien pratique.
Mais imaginons que nous voulions remplir un plus grand vecteur, avec de nombreuses valeur qui n'ont pas de lien entre elles (c'est-à-dire qui ne pourront pas être encodée à l'aide d'une boucle). Par exemple:
Et bien C'EST POSSIBLE !!!
Cela dit, si vous compilez ce code ci-dessus, ça sera autorisé, mais ça ne va pas faire grand chose d'utile.
Revenons à un exemple plus simple, et essayons de construire une structure qui permette cet exemple plus petit:
Ne perdons pas d'esprit que la ligne
v = 1,2,3,4,5;
est équivalente à
(((((v = 1),2),3),4),5);
Il suffirait donc que chaque parenthèse renvoie qqch qui permette à la vrigule qui la suite d'en tirer parti.
Ici, nous allons faire renvoyer à ces parenthèse une nouvelle classe MachinBizarre pointant vers l'adresse de la case du vecteur dans laquelle il faudra ajouter la valeur qui suit. La virgule va recevoir un tel objet, une valeur, et pourra tout mettre dedans. Pour cela, il faut que ce soit l'opérateur = de la classe SuperVecteur qui amorce le mécanisme (avec l'instruction v = 1.
Nous aurons qqch comme ceci:
Qui pourra alors parfaitement être utilisé comme présenté ci-dessus:
(Ne pas confondre surcharge et surdéfinition (je l'ai fais moi-même en annonçant ce post). La surdéfinition consiste à refaire l'implémentation d'un opérateur dans une classé héritée (donc fonctionnement différent que dans la classe parent) et la surcharge consiste à utiliser le même opérateur pour des types différents (on parle alors de polymorphisme).)
Déjà qu'on l'utilise pas souvent cet opérateur virgule, on voudrait en plus le surcharger ? O__o Mais qu'est-ce que c'est que cette idée tordue ?
Oui ben c'est pas une bizarrerie pour rien non plus
Nous allons donc surcharger l'opérateur virgule dans un exemple. Cet opérateur a besoin de deux arguments et renvoie qqch si on le désire. On dit que c'est un opérateur binaire. Comme dans n'importe quelle surcharge, on peut choisir les types nécessaires et qui seront renvoyé, et là c'est au programmeur d'avoir des super idées (l'idée de cet exemple n'est pas de moi, je l'ai trouvée sur un site de programmation (je ne sais plus lequel)).
Imaginons que nous ayons une classe qui représente un vecteur, codée de façon tout à fait naturelle en C++ bien propre. Cela donne quelque chose comme:
- Code:
class SuperVecteur
{
private:
double* racine;
unsigned short taille;
public:
SuperVecteur()
{
racine = NULL;
taille = 0;
}
SuperVecteur(unsigned short _taille)
{
racine = new double[_taille];
for(unsigned short i = 0;i < taille;i++)
racine[i] = 0.0;
taille = _taille;
}
~SuperVecteur()
{
if(racine != NULL)
delete [] racine;
racine = NULL;
}
SuperVecteur(const SuperVecteur& _super_vecteur)
{
racine = new double[_super_vecteur.taille];
for(unsigned short i = 0;i < _super_vecteur.taille;i++)
racine[i] = _super_vecteur.racine[i];
taille = _super_vecteur.taille;
}
SuperVecteur& operator=(const SuperVecteur& _super_vecteur)
{
if(racine != NULL)
delete [] racine;
racine = new double[_super_vecteur.taille];
for(unsigned short i = 0;i < _super_vecteur.taille;i++)
racine[i] = _super_vecteur.racine[i];
taille = _super_vecteur.taille;
return *this;
}
double& operator[](unsigned short i)
{
return racine[i];
}
};
On peut alors utiliser nos vecteurs de la façon suivante, par exemple
- Code:
#include <iostream>
using namespace std;
int main (int argc, char** argv)
{
SuperVecteur v(5);
for(unsigned short i = 0;i < 5;i++)
v[i] = 2.0 * (i + 1);
cout << "v0 = " << v[0] << endl
<< "v1 = " << v[1] << endl
<< "v2 = " << v[2] << endl
<< "v3 = " << v[3] << endl
<< "v4 = " << v[4] << endl;
return 0;
}
Jusque là tout va bien, notre classe est bien pratique.
Mais imaginons que nous voulions remplir un plus grand vecteur, avec de nombreuses valeur qui n'ont pas de lien entre elles (c'est-à-dire qui ne pourront pas être encodée à l'aide d'une boucle). Par exemple:
- Code:
#include <iostream>
using namespace std;
int main (int argc, char** argv)
{
SuperVecteur v(20);
v[0] = 7.3;
v[1] = 47.11;
v[2] = -2.1;
v[3] = 6.0;
v[4] = 44.618;
v[5] = 21.5;
v[6] = -0.04;
v[7] = -111.111;
v[8] = 13.99;
v[9] = -14.1;
v[10] = 21.0;
v[11] = 8.7;
v[12] = 7.3;
v[13] = 3.9;
v[14] = 98.09;
v[15] = -4143.98;
v[16] = -2.0202;
v[17] = -3.99;
v[18] = 11.4505;
v[19] = 38.21;
for(unsigned short i = 0;i < 20;i++)
cout << "v" << i << " = " << v[i];
return 0;
}
- Code:
#include <iostream>
using namespace std;
int main (int argc, char** argv)
{
SuperVecteur v(20);
v = 7.3,47.11,-2.1,6.0,44.618,21.5,-0.04,-111.111,13.99,-14.1,
21.0,8.7,7.3,3.9,98.09,-4143.98,-2.0202,-3.99,11.4505,38.21;
for(unsigned short i = 0;i < 20;i++)
cout << "v" << i << " = " << v[i];
return 0;
}
Et bien C'EST POSSIBLE !!!
Cela dit, si vous compilez ce code ci-dessus, ça sera autorisé, mais ça ne va pas faire grand chose d'utile.
Revenons à un exemple plus simple, et essayons de construire une structure qui permette cet exemple plus petit:
- Code:
#include <iostream>
using namespace std;
int main (int argc, char** argv)
{
SuperVecteur v(5);
v = 1,2,3,4,5;
for(unsigned short i = 0;i < 5;i++)
cout << "v" << i << " = " << v[i];
return 0;
}
Ne perdons pas d'esprit que la ligne
v = 1,2,3,4,5;
est équivalente à
(((((v = 1),2),3),4),5);
Il suffirait donc que chaque parenthèse renvoie qqch qui permette à la vrigule qui la suite d'en tirer parti.
Ici, nous allons faire renvoyer à ces parenthèse une nouvelle classe MachinBizarre pointant vers l'adresse de la case du vecteur dans laquelle il faudra ajouter la valeur qui suit. La virgule va recevoir un tel objet, une valeur, et pourra tout mettre dedans. Pour cela, il faut que ce soit l'opérateur = de la classe SuperVecteur qui amorce le mécanisme (avec l'instruction v = 1.
Nous aurons qqch comme ceci:
- Code:
class MachinBizarre
{
public:
double* racine;
MachinBizarre operator,(double valeur_suivante)
{
racine[0] = valeur_suivante;
MachinBizarre mb;
mb.racine = racine + 1;
return mb;
}
};
class SuperVecteur
{
private:
double* racine;
unsigned short taille;
public:
SuperVecteur()
{
racine = NULL;
taille = 0;
}
SuperVecteur(unsigned short _taille)
{
racine = new double[_taille];
for(unsigned short i = 0;i < taille;i++)
racine[i] = 0.0;
taille = _taille;
}
~SuperVecteur()
{
if(racine != NULL)
delete [] racine;
racine = NULL;
}
SuperVecteur(const SuperVecteur& _super_vecteur)
{
racine = new double[_super_vecteur.taille];
for(unsigned short i = 0;i < _super_vecteur.taille;i++)
racine[i] = _super_vecteur.racine[i];
taille = _super_vecteur.taille;
}
SuperVecteur& operator=(const SuperVecteur& _super_vecteur)
{
if(racine != NULL)
delete [] racine;
racine = new double[_super_vecteur.taille];
for(unsigned short i = 0;i < _super_vecteur.taille;i++)
racine[i] = _super_vecteur.racine[i];
taille = _super_vecteur.taille;
return *this;
}
double& operator[](unsigned short i)
{
return racine[i];
}
MachinBizarre operator=(double premiere_valeur)
{
racine[0] = premiere_valeur;
MachinBizarre mb;
mb.racine = racine + 1;
return mb;
}
};
Qui pourra alors parfaitement être utilisé comme présenté ci-dessus:
- Code:
#include <iostream>
using namespace std;
int main (int argc, char** argv)
{
SuperVecteur v(5);
v = 1,2,3,4,5;
for(unsigned short i = 0;i < 5;i++)
cout << "v" << i << " = " << v[i];
return 0;
}
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Je regarde dès que j'ai un moment !
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Alors, quelques questions à propos du premier bout de code :
1) racine est bien un tableau de double, n'est-ce-pas ? Quelle est la différence entre "double * racine" et "double racine[]" ? J'ai envie de dire aucune...
2) Tu pourrais détailler la ligne SuperVecteur(const SuperVecteur& _super_vecteur) s'il te plait ?
Avant de passer à la suite, juste une petite remarque concernant le 3° morceau de code. L'idéal pour l'améliorer, c'est avec l'opérateur , comme tu le décris. Mais sans surcharger cet opérateur, on peut déjà bien améliorer ce 3° bout de code avec un tableau :
on déclare un tableau tab avec toutes les valeurs du vecteur (1 ligne)
avec un for, on associe chaque tab[i] avec v[i] (2 lignes)
1) racine est bien un tableau de double, n'est-ce-pas ? Quelle est la différence entre "double * racine" et "double racine[]" ? J'ai envie de dire aucune...
2) Tu pourrais détailler la ligne SuperVecteur(const SuperVecteur& _super_vecteur) s'il te plait ?
Avant de passer à la suite, juste une petite remarque concernant le 3° morceau de code. L'idéal pour l'améliorer, c'est avec l'opérateur , comme tu le décris. Mais sans surcharger cet opérateur, on peut déjà bien améliorer ce 3° bout de code avec un tableau :
on déclare un tableau tab avec toutes les valeurs du vecteur (1 ligne)
avec un for, on associe chaque tab[i] avec v[i] (2 lignes)
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
1) Personnellement je n'utilise jamais les vecteur à dimension non fixée (genre double racine[]) parce qu'on ne sait pas très bien ce qu'ils font. Ce qui est sur c'est que double* racine est un pointeur, qui peut être alloué avec new et qui sera désaloué avec delete. La puissance des new, c'est qu'on peut allouer dans une fonction (constructeur par exemple) et désalouer dans une autre (le destructeur typiquement). Ca ne tient pas compte de la visibilité des variables.
Je crois que double racine[] serait un vecteur à taille non prédéfinie mais qui tient compte de la visibilité, et qui sera donc détruit en sortant de la zone où il a été déclaré.
2) Alors ca doit surement être la première fois que tu vois un constructeur de recopie
C'est la fonction qu'il faut fournir à C++ à chaque fois qu'il aura besoin de copier ton objet (par exemple quand tu le passe en paramètre (sans référence) à une fonction, quand il s'agit du résultat d'une fonction qui doit être transmis, etc... Sans quoi il utilisera le constructeur de recopie par défaut, c'est à dire qu'il copiera juste les données de ta classe, et donc seulement le pointeur sans le contenu de la zone pointée; ce qui pourrait amener à des gros ennuis et des segmentation fault.
La méthode que tu propose est simple en effet, mais absolument pas efficace, car tu vas te retrouver à un moment donné avec ton tableau totalement dupliqué dans la mémoire (ce qui gaspille donc ta RAM pour rien), de plus si le tableau est très grand, le temps de traitement risque d'être significativement plus long.
Je crois que double racine[] serait un vecteur à taille non prédéfinie mais qui tient compte de la visibilité, et qui sera donc détruit en sortant de la zone où il a été déclaré.
2) Alors ca doit surement être la première fois que tu vois un constructeur de recopie
C'est la fonction qu'il faut fournir à C++ à chaque fois qu'il aura besoin de copier ton objet (par exemple quand tu le passe en paramètre (sans référence) à une fonction, quand il s'agit du résultat d'une fonction qui doit être transmis, etc... Sans quoi il utilisera le constructeur de recopie par défaut, c'est à dire qu'il copiera juste les données de ta classe, et donc seulement le pointeur sans le contenu de la zone pointée; ce qui pourrait amener à des gros ennuis et des segmentation fault.
La méthode que tu propose est simple en effet, mais absolument pas efficace, car tu vas te retrouver à un moment donné avec ton tableau totalement dupliqué dans la mémoire (ce qui gaspille donc ta RAM pour rien), de plus si le tableau est très grand, le temps de traitement risque d'être significativement plus long.
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
1) et 2) OK.
Sinon mieux qu'un tableau, on pourrait utiliser une liste ou un vector... mais ça sera toujours plus gourmand que ta solution avec l'opérateur ',' .
C'est pas tous les jours que j'utilise cet opérateur, mais il est bien efficace ! Ca pourra toujours me servir un jour ou l'autre !
Sinon mieux qu'un tableau, on pourrait utiliser une liste ou un vector... mais ça sera toujours plus gourmand que ta solution avec l'opérateur ',' .
C'est pas tous les jours que j'utilise cet opérateur, mais il est bien efficace ! Ca pourra toujours me servir un jour ou l'autre !
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Ca ne résoud pas le problème des données dupliquées pour rien
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Ben si on travaille dessus après, (si on supprime des coordonnées par exemple) pour un tableau c'est en dur, mais pour un vector la taille est dynamique. Mais à la copie du vector ou du tableau, TOUT est recopié en effet.
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Re: [C++] Amusons-nous avec le C++
Non ce que je veux dire c'est que ton tableau temporaire sera détruit après avoir copié son contenu. Par conséquent, juste avant qu'il soit détruit, le tableau existe en double dans la RAM, une fois dans la structure SuperVecteur et une fois dans la structure du tableau lui-même.
Alors qu'avec ma méthode c'est une lecture du code valeur par valeur, et rien n'est dédoublé.
Alors qu'avec ma méthode c'est une lecture du code valeur par valeur, et rien n'est dédoublé.
Duche- Modérateur
- Nombre de messages : 2210
Age : 39
Localisation : Louvain-la-Neuve (Belgique)
Profession / Etudes : Développeur en optimisation
Points : 8278
Date d'inscription : 16/01/2006
Re: [C++] Amusons-nous avec le C++
Ah ok ok !
Julien- Administrateur
- Nombre de messages : 12291
Age : 37
Localisation : Clermont-Ferrand
Profession / Etudes : Ingénieur
Points : 22512
Date d'inscription : 10/03/2005
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|
Jeu 2 Juil 2015 - 15:16 par louaraychi
» Devoir maison sur équilibre et réaction chimique
Dim 1 Fév 2015 - 17:19 par sararose
» Ma présentation
Sam 25 Oct 2014 - 23:29 par Rith
» projet scientique sur la LUMIERE
Ven 26 Sep 2014 - 20:33 par benjamin-010
» La trajectoire de la Terre
Mar 5 Aoû 2014 - 22:19 par Alban
» Equilibrer une réaction redox
Dim 8 Juin 2014 - 21:18 par Courtney ♥
» les effets sur les lignes de transport de l’électricité
Ven 30 Mai 2014 - 17:14 par leila14
» lignes de transport de l'électricité
Ven 30 Mai 2014 - 17:07 par leila14
» Gravitation
Ven 16 Mai 2014 - 20:16 par fatimaa
» Maquette suspension de moto 2D
Jeu 17 Avr 2014 - 17:20 par Sti2d