Tout d'abord, quelques règles de base:
Utilisez-le std::unique_ptr
comme pointeur intelligent sans surcharge. Vous ne devriez pas avoir à vous embêter avec des pointeurs bruts très souvent. std::shared_ptr
est également inutile dans la plupart des cas. Le désir de propriété partagée trahit souvent un manque de réflexion sur la propriété en premier lieu.
Utilisez std::array
ce paramètre pour les tableaux de longueur statique et std::vector
pour les dynamiques.
Utilisez intensivement des algorithmes génériques, en particulier:
<algorithm>
<numeric>
<iterator>
<functional>
Utiliser auto
et decltype()
partout où ils bénéficient de lisibilité. En particulier, lorsque vous souhaitez déclarer une chose, mais d'un type qui vous importe peu, tel qu'un type d'itérateur ou de modèle complexe, utilisez auto
. Lorsque vous voulez déclarer une chose en fonction du type d’autre chose, utilisez decltype()
.
Sécurisez les choses quand vous le pouvez. Lorsque vous avez des assertions qui appliquent des invariants sur un type particulier de choses, cette logique peut être centralisée dans un type. Et cela n’entraîne pas nécessairement de frais généraux d’exécution. Il va sans dire que les conversions de style C ( (T)x
) doivent être évitées au profit de préfigurations plus explicites (et consultables!) (Par exemple, de type C ++ static_cast
).
Enfin, sachez comment la règle de trois:
- Destructeur
- Copier le constructeur
- Opérateur d'assignation
Est devenue la règle de cinq avec l'ajout du constructeur de déplacement et de l'opérateur d'affectation de déplacement. Et comprendre les références rvalue en général et comment éviter de copier.
C ++ est un langage complexe, il est donc difficile de caractériser la meilleure façon d'utiliser l' ensemble de celui - ci. Mais les pratiques d'un bon développement C ++ n'ont pas fondamentalement changé avec C ++ 11. Vous devez toujours préférer les conteneurs gérés par la mémoire à la gestion manuelle de la mémoire - les pointeurs intelligents facilitent cette tâche.
Je dirais que le C ++ moderne est en effet essentiellement exempt de gestion de mémoire manuelle. L'avantage du modèle de mémoire du C ++ est qu'il est déterministe , et non manuel. Les désallocations prévisibles permettent des performances plus prévisibles.
En ce qui concerne un compilateur, G ++ et Clang sont à la fois compétitifs en termes de fonctionnalités C ++ 11 et en rattrapant rapidement leurs lacunes. Je n'utilise pas Visual Studio, je ne peux donc parler ni pour ni contre.
Enfin, une note sur std::for_each
: évitez-le en général.
transform
, accumulate
Et erase
- remove_if
sont bon vieux fonctionnels map
, fold
et filter
. Mais for_each
est plus général et donc moins significatif - il n’exprime aucune intention autre que la boucle. En outre, il est utilisé dans les mêmes situations que celles basées sur les plages for
et est syntaxiquement plus lourd, même lorsqu'il est utilisé sans aucun point. Considérer:
for (const auto i : container)
std::cout << i << '\n';
std::for_each(container.begin(), container.end(), [](int i) {
std::cout << i << '\n';
});
for (const auto i : container)
frobnicate(i);
std::for_each(container.begin(), container.end(), frobnicate);