mikizi a écrit :
C-- ça veut dire de la mauvaise programmation en C++? Je fais cela tout simplement parce que je fais les choses dans l'ordre du cours que je suis : d'abord les références et les pointeurs, puis les classes, héritage etc. Par conséquent , je n'ai pas encore vu ce que signifie std::vector.
|
C'est pourtant une des premières choses que tu devrais apprendre, si c'était un vrai cours de C++, et pas un cours de C a la sauce objet pour faire illusion.
Payes toi le Koenig et Moo, Accelerated C++, si tu veux un exemple de bouquin qui t'apprenne correctement le C++. std::vector est une des premières notions qui y est exposée (au chapitre 3, après std::string) tandis que les arrays n'apparaissent que 100 pages plus loin (au chapitre 10).
Bon sinon, une réponse rapide pour l'utilité des références:
Code :
- void allocationTab (int* tab, int n){
- tab=new int[n];
- }
|
En C++, tu regardes quels paramètres ont leur valeur (volontairement) modifiée par la fonction, la modification de cette valeur étant une des raisons de création de ta fonction. Ces paramètre la, tu les passes par référence (tu fais suivre le type du paramètre par & dans la déclaration et définition de ta fonction). Sans cela, en sortie de la fonction, les valeurs modifiées dans la fonction sont oubliées, et tu vas te retrouver avec la même valeur qu'a l'entrée de la fonction.
Ici c'est simple:
La fonction 1) crée un array d'entiers de taille n et 2) met l'adresse de la première case de l'array dans tab.
Donc des deux paramètres, tab est modifié par la fonction, et c'est volontaire, on veut la valeur modifiée de tab après avoir appelé la fonction, tandis que n est juste une valeur utilisée par la fonction.
On va donc faire:
Code :
- void allocationTab (int*& tab, int n){
- tab=new int[n];
- }
|
pour que ça marche.
Si tu as compris cela, tu as compris pourquoi on doit faire aussi:
Code :
- void desallocationTab(int*& tab){
- ....
- }
|
La suite des explications pour cette fonction la est la fin de ce post.
Passons maintenant à celle ci:
Code :
- void remplissageTab(int* tab, int n){
- for(int i=0; i<n;i++){
- cin >> tab[i];
- }
- }
|
Cette fonction marche, et c'est une fonction similaire qu'on utiliserait si on faisait du C (avec autre chose que cin qui n'existe pas en C). Mais on est en C++, et C++, c'est ++ puissant!
Cette fonction, elle remplit les cases de l'array. On ne veut pas changer l'array lui même entre l'entrée et la sortie, mais juste changer les valeurs des cases de l'array.
Déjà, on ne passe pas l'array en paramètre ce qui va permettre d'être sur d'avoir en sortie le même qu'en entrée. Mais comment être sur dans la fonction, je vais pas changer (involontairement) cet array pour un autre, quitte à perdre cette modification en sortant de la fonction? comment être sur qu'on va toujours utiliser notre array et pas un autre?
C++ permet de s'en assurer grâce au mot clé const, qui permet d'être sur que la valeur va être constante, et ne pas changer.
int* const tab va dire au compilateur que tab est constant et ne peut changer. On va alors être sur que tab, dans la fonction, va toujours être notre array de départ, parce que si on veut modifier tab, le compilateur va éructer une bordée d'insultes et refuser de compiler le programme jusqu'au bout.
Donc ça,
Code :
- void remplissageTab(int* tab, int n){
- for(int i=0; i<n;i++){
- cin >> tab[i];
- }
- }
|
ça marchait, mais ceci:
Code :
- void remplissageTab(int* const tab, int n){
- for(int i=0; i<n;i++){
- cin >> tab[i];
- }
- }
|
va nous garantir que tab va toujours être notre tableau d'entrée au cours de la fonction. C'est ce que JoelF a appelé un contrat de la fonction remplissageTab.
Passons à la dernière:
Code :
- int sommeTab(int* tab, int n){
- int sum=0;
- for (int i=0; i<n; i++){
- sum+=tab[i];
- }
- return sum;
- }
|
Ici, on veut faire un calcul avec les valeurs des cases de tab. On ne veut ni que tab, ni que les valeurs des cases de tab ne soient modifiées par la fonction.
Déjà, pour que tab ne soit pas modifié, on l'a vu, on va écrire: int* const tab
Pour que les entiers dans les cases de tab ne soient pas modifiés, on va aussi les déclarer constants: const int* const tab
D'ou la forme finale
Code :
- int sommeTab(const int* const tab, int n){
- int sum=0;
- for (int i=0; i<n; i++){
- sum+=tab[i];
- }
- return sum;
- }
|
Point final:
quand on fait tab=new int[n]; dans allocationTab, on fait, comme écrit plus haut:
La fonction 1) crée un array d'entiers de taille n et 2) met l'adresse de la première case de l'array dans tab.
Quand on fait delete[] tab; dans desallocationTab, on ne fait que faire l'inverse du 1): on détruit l'array d'entier de taille n.
Reste a faire l'opération inverse du 2: enlever l'adresse, et mettre une adresse qui ne soit plus celle d'une case contenant un entier (ni de rien du tout). L'adresse de valeur 0 est spécialement la pour cela, aucun objet ne peut avoir pour adresse 0, et on va l'utiliser, en faisant: tab = 0; On est maintenant sur que tab ne pointe plus vers un tableau d'entiers. Et si plus tard, quelqu'un veut savoir si tab pointe vers quelque chose, en voyant que tab vaut 0, il va savoir que ce n'est pas le cas.
d'ou la version finale:
Code :
- void desallocationTab(int*& tab){
- delete[] tab;
- tab = 0;
- }
|
A+,
Message édité par gilou le 19-08-2011 à 19:16:54
---------------
There's more than what can be linked! -- Iyashikei Anime Forever! -- AngularJS c'est un framework d'engulé! --