comme vous le savez déjà, le C++ permet la surcharge d'opérateurs. ce soir, on se penche sur l'opérateur d'incrémentation (tout ce qui sera dit ici est valable pour l'opérateur de décrémentation)
l'opérateur ++ existe sous 2 formes: la post et la pre incrémentation (i++ et ++i). Je ne fais pas de rappels sur l'utilisation.
Nous allons voir comment les surcharger et pourquoi les killers utilisent toujours quand ils le peuvent l'opérateur de pré-incrémentation.
pour la première partie, le code parle de lui même.
- pré-incrémentation Taz& operator++(), pas de problème on peut renvoyer une référence à l'object
- post-incrémentation Taz operator++(int), on revoie une copie selon la sémantique générale (le paramètre int sert uniquement à différencier les versions)
pour la deuxième partie: i++ est en fait une surcouche à ++i. penser à son coportement: incrémenter i et retourner son ancienne valeur, c'est donc tres facile à implémenter à partir de ++i. tout l'enjeu consiste à retourner l'ancienne valeur, il faut donc mémoriser une copie: si on en s'en sert OK, sinon quel gachis! vous allez me dire, ça ne coute rien... mais sur un objet, si. pensez aux itérateurs qui vous permettent de vous ballader à travers de (très) grandes séquences: vous ecriver i++ et à chaque fois vous créez sans le savoir un itérateur inutile. je vous rassure tout de suite, pour les types de bases, le compilateur optimise ce genre de chose. mais pour vos types persos, encore heureux qu'il fasse ce qu'on lui dit. Pensez qu'un itérateur c'est souvent 2/3 pointeurs: j'ai récemment eu l'exemple d'un iterateur pesant 12*8 octets. Les copies inutiles ça peut donc vous pénaliser, et surtout, c'est trop bête puisque c'est inutile.
petit exemple de code pour vous convaincre
Code :
- #include <iostream>
- using namespace std;
- class Taz
- {
- int i;
-
- public:
-
- Taz()
- {
- cout << "Constructeur trivial" << " &" << &i << endl;
- }
-
- /* explicit */ Taz(int j)
- : i(j)
- {
- cout << "Constructeur i = " << i << " &" << &i << endl;
- }
-
- Taz(const Taz &f)
- : i(f.i)
- {
- cout << "Constructeur par recopie i = " << i << " &" << &i << " (source &" << &f.i << ')' << endl;
- }
-
- ~Taz()
- {
- cout << "~Destructeur i = " << i << " &" << &i << endl;
- }
-
- Taz& operator+=(const Taz &other)
- {
- this->i+=other.i;
- return *this;
- }
-
- Taz& operator++()
- {
- cout << "pre-incrementation" << endl;
- ++i;
- return *this;
- }
- Taz operator++(int)
- {
- cout << "post-incrementation" << endl;
- Taz temp(*this);
- ++i;
- cout << "Copie de retour ";
- return temp;
- }
- };
- int main()
- {
- Taz a;
- cout << endl;
- a++;
- cout << endl;
- ++a;
- cout << endl;
- }
|
Message édité par Taz le 06-09-2003 à 13:22:16