Références de déplacement et références constantes et recopie
const int
\neq int
, ils ont le même type mais un objet différent.
Il faut toujours initalisé les
const
.
void f(const int a) { ... }
void f(int a) { ... }
int main(void) {
int i;
const int ci = 4;
int *p;
const int* p2;
const int* const p3 = &i;
int *const p4 = &i; /* on peut pas faire = &ci car on pointerais vers
* une const */
// p = &ci /* pareil on ne doit pas modifier
/* une const donc impossible de faire ça */
return 0;
}
Utilisation dans des classes
#include<iostream>
using namespace std;
class A {
// private: // privé par défaut donc inutile
const int a;
const int b;
public:
A(int pa, int pb = 4) : a(pa), b(pb) { } /* l'ordre est important
* c'est a, puis b, car on
* demande pa, puis pb
* (respect de l'ordre de
* construction) */
voidafficher(void) {
cout << a << endl;
cout << b << endl;
}
};
int main(void) {
A objet1(3, 6);
objet1.afficher();
A objet2(3);
objet2.afficher();
return 0;
}
Références constantes
int main(void) {
int a = 1;
const int& r = a;
// r = 3; // impossible, on ne peut pas modifier depuis une const
a = 2; // possible
const int& r = b; // possible
// int& r2 = b; // impossible aussi pour la même raison que précedemment
return 0;
}
Une
rvalue
peut être référencé à l’aide d’une référence constante.
#include<iostream>
using namespace std;
class A {
const int a;
const int b;
public:
A(int pa, int pb = 4) : a(pa), b(pb) { }
voidafficher(void) const { // mot clé const ici !!!
cout << a << endl;
cout << b << endl;
}
};
A g(void) {
// autre syntaxe pour appeller le constructeur
return A { 2 };
}
int main(void) {
int a;
int& r = a;
const A& r1 = g();
r1.afficher();
// encore une autre syntaxe de constructeur
A objet = 4; /* == objet { 4 }; --> valable que quand
* il n'y a qu'un seul
* paramètre */
return 0;
}
Explication de pourquoi on a le mot clé const à la suite de la fonction
Explicit le fait que la fonction ne modifie rien à l’objet.
-> Si on utilises const à mauvais escient, le compilateur refusera de compiler.
-> Si on veut quand même modifier quelque chose dans la fonction const
, il faut le faire sur un attribut mutable
-> Mot clé static
permet qu’une valeure soit gardé d’un objet à l’autre quand définie dans une classe.
Exemple
#include<iostream>
using namespace std;
class Paire {
int a;
int b;
mutable int temp;
static int nb; /* ici c'est une déclaration pour
* pouvoir le définir à l'exterieur */
public:
Paire(int pa, int pb) {
a = pa;
b = pb;
nb++;
}
void afficher(void) const {
temp = 1;
cout << "p: " << a << ", s: " << b << endl;
}
static int compter() {
return nb;
}
~Paire() {
nb--;
}
};
int Paire::nb = 0; // ici c'est une définition (dans un seul fichier objet)
int main(void) {
cout << Paire::compter() << endl; // on l'appel en dehors de la classe
Paire const a(4, 2);
a.afficher();
cout << Paire::compter() << endl;
{
Paire b(1, 1);
cout << Paire::compter() << endl; // on l'appel en dehors de la classe
Paire c(1, 1);
cout << Paire::compter() << endl; // on l'appel en dehors de la classe
}
cout << Paire::compter() << endl; // on l'appel en dehors de la classe
return 0;
}
Une variable static
doit être définie à l’extérieur car elle est unique, il faut donc la définir en dehors de la classe pour que “tout le monde” soit au courant que cette variable est reservée.
Constructeur de recopie tab
#include<iostream>
using namespace std;
class Tab {
int* tab;
// int taille; -> on se dit que tout les tableaux sont de taille 10
public:
Tab(void) {
cout << "appel du constructeur" << endl;
tab = new int[10];
for(int i = 0; i < 10; i++)
tab[i] = 0;
}
Tab(Tab const &original) { // ici c'est le constructeur de recopie
cout << "appel du constructeur de copie" << endl;
tab = new int[10];
for(int i = 0; i < 10; i++)
tab[i] = original.tab[i];
}
void set(int indice, int val) {
tab[indice] = val;
}
void afficher(void) {
for(int i = 0; i < 10; i++) {
cout << tab[i];
cout << " ";
}
cout << endl;
}
~Tab() {
cout << "appel du destructeur" << endl;
delete[] tab;
}
};
void f(Tab b) {
b.set(3, 1);
b.afficher();
}
int main(void) {
Tab a;
a.set(3, 5);
a.afficher();
f(a);
a.afficher();
return 0;
}
Le constructeur de recopie est appellée automatiquement lors d’un appel de fonction.