Je suis en train de programmer en C ++ depuis un moment, mais je me concentre principalement sur les fonctionnalités de bas niveau du C ++. Par cela, je veux dire principalement travailler avec des pointeurs et des tableaux bruts. Je pense que ce comportement est connu comme utilisant C ++ en tant que C avec des classes. Malgré cela, je n’ai essayé le C que récemment pour la première fois. J'ai été agréablement surpris de voir comment des langages tels que C # et Java masquent ces détails dans des classes de bibliothèques standard pratiques telles que Dictionnaires et Listes.
Je suis conscient que la bibliothèque standard C ++ contient de nombreux conteneurs tels que des vecteurs, des cartes et des chaînes. C ++ 11 ne fait qu'ajouter à cela en proposant std :: array et des boucles à distance.
Comment apprendre à utiliser au mieux ces fonctionnalités du langage moderne et celles qui conviennent à quels moments? Est-il exact que de nos jours, l'ingénierie logicielle en C ++ est pratiquement dépourvue de gestion manuelle de la mémoire?
Enfin, quel compilateur devrais-je utiliser pour tirer le meilleur parti de la nouvelle norme? Visual Studio possède d’excellents outils de débogage, mais même VS2012 semble avoir un support C ++ 11 terrible.
g++ -std=c++11
Réponses:
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 etstd::vector
pour les dynamiques.Utilisez intensivement des algorithmes génériques, en particulier:
<algorithm>
<numeric>
<iterator>
<functional>
Utiliser
auto
etdecltype()
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, utilisezauto
. Lorsque vous voulez déclarer une chose en fonction du type d’autre chose, utilisezdecltype()
.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:
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
Eterase
-remove_if
sont bon vieux fonctionnelsmap
,fold
etfilter
. Maisfor_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 plagesfor
et est syntaxiquement plus lourd, même lorsqu'il est utilisé sans aucun point. Considérer:la source
std::for_each
j'aurais prévu la plage basée sur la boucle comme un meilleur remplacement que simplefor
.std::for_each
, pas avec la gamme . Je l'ai enlevé pour éviter toute confusion.std::for_each()
. Quand vous avez du lambda, c'est certainement mieux qu'unefor
boucle classique . Avec unefor
boucle basée sur une plage, ce n'est peut-être pas le cas, mais vous n'avez pas écrit "for
boucle basée sur une plage ".for
boucle» inclut «for
boucle basée sur la portée ». J'ai édité avec plus d'explications et un exemple pour clarifier, merci.Comme point de départ:
char*
pour les chaînes. Utilisezstd::string
oustd::wstring
et regardez simplement votre code devenir plus court, plus lisible et plus sûr[ ]
) et utilisezstd::vector
ou toute autre classe de conteneur appropriée. Les bonnes choses à propos destd::vector
c’est qu’elle connaît sa propre longueur, qu’elle nettoie son contenu quand elle sort du cadre, qu’elle est facile à itérer et qu’elle s’agrandit lorsque vous ajoutez plus d’articles. Mais il existe d’autres collections qui pourraient fonctionner encore mieux dans votre cas.std::unique_ptr
- et apprenezstd::move
presque immédiatement. Étant donné que cela peut donner lieu à des objets noncopyable, la paresse vous pouvez envoyer de temps en temps versstd::shared_ptr
- et vous pouvez avoir des cas véritables d'utilisation pourstd::shared_ptr
ainsiauto
lorsque vous déclarez des itérateurs et des types qui dépendent de déclarations antérieures (par exemple, vous avez précédemment déclaré un vecteur de quelque chose, maintenant vous déclarez quelque chose, utilisez-leauto
)for_each
sur un "raw for" chaque fois que vous le pouvez, cela évite aux autres lecteurs de lire votre boucle avec soin pour en conclure que vous êtes en train d'itérer sur l'ensemble de la collection, etc. Si votre compilateur prend en charge "range for", utilisez-lefor_each
. Apprenez les appels algorithme triviales commeiota
,generate
,accumulate
,find_if
et ainsi de suite.Ne vous énervez pas trop sur le compilateur à utiliser. Le manque "terrible, affreux" de prise en charge de C ++ 11 dans VS2012 réside dans le fait qu'il n'y a pas de modèles variadiques (oui, vous étiez sur le point d'utiliser des modèles variadiques) et que l'
{}
initialiseur n'existe pas. Je le veux aussi mais je vais à peine arrêter d'utiliser un outil de développement utile.La deuxième chose à faire, après avoir embrassé
std::
, est de commencer à penser à RAII. Chaque fois que vous avezVous avez alors un constructeur, un certain nombre de fonctions membres et un destructeur. Ecrivez un cours qui s’occupe de cela pour vous. Vous pourriez même pas avoir à écrire le ctor et le dtor. L'inclusion
shared_ptr
d'une variable en tant que membre d'une classe est un exemple de code RAII. Vous n'écrivez pas de code de gestion de la mémoire, mais lorsque votre instance sort de son périmètre, les choses se passent bien. Développez cette réflexion pour couvrir des éléments tels que la fermeture de fichiers, la libération de poignées, de verrous, etc. et le code deviendra simplement plus simple et plus petit (tout en éliminant les fuites) sous vos yeux.Si vous vous sentez vraiment en confiance, éliminez-vous
printf
en faveur decout
, supprimez les macros#define
et commencez à apprendre quelques "idiomes avancés" comme PIMPL. J'ai tout un cours sur ce sujet chez Pluralsight que vous pouvez probablement visionner avec leur essai gratuit.la source
En programmant. L'expérience est la meilleure façon d'apprendre.
C ++ 11 comporte de nombreuses nouvelles fonctionnalités (auto, rvalue, nouveaux pointeurs intelligents, pour n'en nommer que quelques-unes). Le mieux est de commencer à les utiliser et à les consulter chaque fois que vous le pouvez et chaque fois que vous trouvez un article intéressant.
Cela dépend de ce que vous devez faire. La plupart des applications peuvent se passer de pointeurs intelligents et oublier la gestion de la mémoire. Il reste encore des applications qui ne peuvent pas s’échapper aussi facilement (par exemple, si elles ont besoin d’un nouvel emplacement ou d’un allocateur de mémoire personnalisé pour une raison quelconque).
Si vous devez utiliser Qt, vous devrez utiliser leurs règles pour la gestion de la mémoire.
Tout ce que vous avez sous la main qui supporte le dernier standard:
mais aucun compilateur ne supporte toutes les fonctionnalités.
la source
Mon université utilise encore le C ++ pour enseigner. J'ai programmé avec C ++ pendant 5 ans et maintenant je suis un étudiant diplômé. Bien sûr, maintenant, j'utilise beaucoup Java, Ruby, etc. Je vous recommande vivement de ne pas vous hâter au sujet de ces fonctionnalités dans un langage comme Java. D'après mon expérience et mon opinion, après les fonctionnalités de bas niveau du C ++. Vous devriez vous pencher sur des sujets tels que la programmation générique avec C / C ++, comme la création de classe de modèle, les fonctions de modèle, le remplacement d'opérateur, les méthodes virtuelles, les pointeurs intelligents. Pour la pièce de conception orientée objet, il existe de nombreuses fonctionnalités que C ++ possède et que Java n’a pas, comme le multi-héritage. L'héritage est puissant mais dangereux aussi. Le niveau d'implémentation de la conception orientée objet en C ++ est également un bon sujet. La communication inter-processus, les threads, sont également importants en C ++.
Pour le compilateur et le débogueur. Je sais que Visual Studio est génial. Mais je vous recommande vraiment d'apprendre GDB, Valgrind et Make still, et d'être bon avec ces outils. Microsoft est génial, mais il a fait trop de choses pour vous. En tant qu'étudiant, vous devez vraiment apprendre ces choses que Microsoft a faites vous aussi. Pour le compilateur, G ++ est une bonne chose de GNU.
Après tout, après tant d’années, j’ai vraiment le sentiment que les fonctionnalités les plus importantes sont les fonctionnalités de bas niveau telles que la matrice brute. Le vecteur est vraiment juste un tableau dynamique. Ce sont mes recommandations, quelque chose peut-être trop subjectif, prenez ce que vous pensez être juste.
la source