Avec la nouvelle norme, il existe de nouvelles façons de faire les choses, et beaucoup sont plus agréables que les anciennes, mais l'ancienne est toujours valable. Il est également clair que la nouvelle norme ne déprécie pas officiellement beaucoup, pour des raisons de compatibilité ascendante. La question qui reste est donc:
Quelles anciennes méthodes de codage sont nettement inférieures aux styles C++ 11 et que pouvons-nous faire maintenant à la place?
En répondant à cette question, vous pouvez sauter les choses évidentes telles que "utiliser des variables automatiques".
final
pour empêcher la dérivation de classe.std::auto_ptr
Fonctionne ne sont plus nécessaires en raison de la prise en charge de première classe des références rvalue.shrink_to_fit()
, ce qui devrait permettre d'éviter l'échange de données par un temporaire.= delete
Est une façon beaucoup plus directe de dire qu'une fonctionnalité particulière est explicitement refusée. Ceci s’applique pour empêcher l’allocation de tas (c.-à-d., =delete
Pour le membre operator new
), Empêcher les copies, les affectations, etc.result_of
: Les utilisations du modèle de classe result_of
Doivent être remplacées par decltype
. Je pense que result_of
Utilise decltype
quand il est disponible.NULL
devrait être redéfini en tant que nullptr
, mais voyez conversation de STL pour savoir pourquoi ils l'ont décidé.Je pense que je vais m'arrêter là!
À un moment donné, on a prétendu qu'il fallait retourner par valeur const
plutôt que par valeur:
const A foo();
^^^^^
C'était en grande partie inoffensif en C++ 98/03, et peut même avoir attrapé quelques bugs qui ressemblaient à:
foo() = a;
Mais retourner par const
est contre-indiqué en C++ 11 car il inhibe la sémantique de déplacement:
A a = foo(); // foo will copy into a instead of move into it
Alors détendez-vous et codez:
A foo(); // return by non-const value
Dès que vous pouvez abandonner 0
Et NULL
en faveur de nullptr
, faites-le!
Dans le code non générique, l'utilisation de 0
Ou NULL
n'est pas si grave. Mais dès que vous commencez à transmettre des constantes de pointeur nul dans le code générique, la situation change rapidement. Lorsque vous transmettez 0
À une template<class T> func(T)
T
, elle est déduite en tant que int
et non en tant que constante de pointeur null. Et il ne peut pas être reconverti en constante de pointeur null après cela. Cela tombe dans un bourbier de problèmes qui n'existent tout simplement pas si l'univers n'utilisait que nullptr
.
C++ 11 ne déprécie pas 0
Et NULL
en tant que constantes de pointeur nul. Mais vous devriez coder comme si c'était le cas.
idiome de sécurité → explicit operator bool()
.
Constructeurs de copie privée (boost :: noncopyable) → X(const X&) = delete
Simulation de la classe finale avec destructeur privé et héritage virtuel → class X final
Une des choses qui vous empêche simplement d'écrire des algorithmes de base en C++ 11 est la disponibilité de lambdas en combinaison avec les algorithmes fournis par la bibliothèque standard.
J'utilise ceux-ci maintenant et c'est incroyable combien de fois vous dites simplement ce que vous voulez faire en utilisant count_if (), for_each () ou d'autres algorithmes au lieu d'avoir à écrire à nouveau ces fichues boucles.
Une fois que vous utilisez un compilateur C++ 11 avec une bibliothèque standard complète C++ 11, vous n’avez plus aucune excuse pour ne pas utiliser les algorithmes standard pour construire le vôtre. Lambda juste le tuer.
Pourquoi?
En pratique (après avoir utilisé moi-même cette méthode d'écriture d'algorithmes), il est beaucoup plus facile de lire quelque chose qui est construit avec des mots simples qui veulent dire ce qui est fait plutôt qu'avec certaines boucles qu'il faut déchiffrer pour en connaître le sens. Cela dit, déduire automatiquement les arguments lambda aiderait beaucoup à rendre la syntaxe plus facilement comparable à une boucle brute.
Fondamentalement, les algorithmes de lecture réalisés avec des algorithmes standard sont beaucoup plus faciles que des mots masquant les détails d'implémentation des boucles.
J'imagine que seuls les algorithmes de niveau supérieur doivent être pris en compte maintenant que nous avons des algorithmes de niveau inférieur sur lesquels s'appuyer.
Vous devrez moins souvent implémenter des versions personnalisées de swap
. En C++ 03, un swap
non-jetable efficace est souvent nécessaire pour éviter les copies coûteuses et jettées, et depuis std::swap
utilise deux copies, swap
doit souvent être personnalisé. En C++, std::swap
utilise move
, et donc l’accent est mis sur l’implémentation de constructeurs de mouvements efficaces et non générateurs et d’opérateurs d’affectation de déplacements. Comme pour ceux-ci, la valeur par défaut est souvent correcte, ce sera beaucoup moins de travail qu'en C++ 03.
En général, il est difficile de prédire quels idiomes seront utilisés car ils sont créés par l'expérience. Nous pouvons nous attendre à un "Effective C++ 11" peut-être l'année prochaine, et à un "Standard de codage C++ 11" dans trois ans seulement, car l'expérience nécessaire fait défaut.
Je ne connais pas son nom, mais le code C++ 03 a souvent utilisé la construction suivante pour remplacer l'affectation de déplacement manquante:
std::map<Big, Bigger> createBigMap(); // returns by value
void example ()
{
std::map<Big, Bigger> map;
// ... some code using map
createBigMap().swap(map); // cheap swap
}
Cela évitait toute copie en raison de la copie combinée avec le swap
ci-dessus.
Le retour par valeur n'est plus un problème. Avec la sémantique de déplacement et/ou l’optimisation de la valeur de retour (dépendant du compilateur), les fonctions de codage sont plus naturelles, sans surcoût ni coût (la plupart du temps).
Quand j'ai remarqué qu'un compilateur utilisant le standard C++ 11 ne corrige plus le code suivant:
std::vector<std::vector<int>> a;
pour soi-disant opérateur contenant >>, j'ai commencé à danser. Dans les versions précédentes, il faudrait faire
std::vector<std::vector<int> > a;
Pour aggraver les choses, si jamais vous deviez déboguer ceci, vous savez à quel point les messages d'erreur qui en résultent sont horribles.
Cependant, je ne sais pas si cela vous paraissait "évident".