Débuter en C++

Le problème exposé dans ce sujet a été résolu.

Bonjour tout le monde :)

Comme pas mal de personnes, j'ai suivi le cours de C++ d'OpenClassroom (avec tous ses défauts). J'ai entre temps suivi celui de Guillaume Belz et je m'attelle à corriger les mauvaises pratiques d'OC.

1) Pour l'initialisation d'une variable, les accolades doivent-elles être préférées dans les cas suivants : - int valeur { tableau[0] } - int taille { tableau.size() } - int* pointeur { 0 }

2) J'essaye de mettre des const aussi souvent que possible. Dans les cas simples, peut-on dire que les paramètres et les conditions de fin de boucle sont des constantes ?

3) Quelle convention préférer pour les pointeurs int pointeur ou int pointeur ?

4) Où puis-je trouver les "conventions" utilisées par les programmeurs pour nommer les variables : par exemple isVariable pour un booléen, pVariable pour un pointeur (?), index/idx/indice pour la variable qu'on itère dans une boucle ?

5) Enfin, avez vous un cours en anglais à me conseiller qui est aussi à jour que celui de Guillaume ? (Je suis pressé de lire la suite du cours sur la POO).

Merci beaucoup pour votre aide :)

1) oui, par défaut, toujours préférer les accolades.

Pour aller un peu plus loin : il y a en fait (je pense) qu'un seul cas ou il ne faut pas utiliser les accolades : lorsque l'on ne veut pas "forcer" l'initialisation d'une variable. Par exemple un tableau de données important, dont les valeurs seront directement modifiées sans être lue (et donc que les valeurs aléatoires que le tableau contiendrait ne sera pas problématiques). Bien sur, comme toujours quand on parle d'optimisation, après avoir profiler/benchmarker tout cela pour montrer que cela a un impact significatif sur les perfs.

Et pour le pointeur : a éviter (je ferais un chapitre dessus, il y a beaucoup a dire. Et même si c'est pas du C++ "moderne", ca serait casse gueule de ne pas en parler, au moins pour savoir les problèmes que cela pose)

2) pas sur de comprendre de quoi tu parles. Si tu parles de :

1
2
const auto s { v.size() };  // const ici ou pas ?
for (decltype(s) i {}; i < s; ++i) ...

En fait, il n'est pas nécessaire de déclarer une variable en dehors du for. Premièrement, cela créée une variable qui a une portée plus large que ce dont on a besoin. Deuxièmement, les compilos modernes savent détecter l'invariance de size() dans la boucle et optimiser cela (si la const est respectée)

Et comme toujours (cf au dessus) : profiling avant d'optimiser. (Dit autrement, tu peux déclarer une variable si tu veux… mais il faut montrer les benchmarks)

3) pas de pointeurs.

Sinon, je n'ai pas compris la question.

4) il suffit de recherche "code guideline" sur internet. Chaque logiciel a ses propres règles (parfois dérivées de règles plus commune, par exemple les "google code guideline"). En C++, pas de règles fixees, le plus commune sont (a mon avis) :

  • celle de la STL et boost (minuscule, underscore, membres commencent par _, etc). A utiliser quand on fait un projet pure C++
  • celle de Qt (majuscule, pas de underscore, nom des classes commencent avec une majuscule et variables avec une minuscule, membres commencent pas m_, etc)

5) C++ Primer de Lippmann.

Et moi aussi, j'aimerais en voir la fin de ce cours :)

+2 -0

Merci pour votre aide :)

2) Oui je voulais dire dois-je déclarer le s constant ;)

3) L'éditeur a utilisé de l'italique à la place de * . Je voulais dire où faut-il placer l'astérisque. J'avais déjà lu des critiques sur le pointeur en C++ mais j'utilise la library PCL et il faut utiliser des pointeurs http://docs.pointclouds.org/1.7.1/classpcl_1_1_point_cloud.html ou encore avec Matlab http://de.mathworks.com/help/matlab/apiref/mexfunction.html

3) L'éditeur a utilisé de l'italique à la place de * . Je voulais dire où faut-il placer l'astérisque. J'avais déjà lu des critiques sur le pointeur en C++ mais j'utilise la library PCL et il faut utiliser des pointeurs http://docs.pointclouds.org/1.7.1/classpcl_1_1_point_cloud.html ou encore avec Matlab http://de.mathworks.com/help/matlab/apiref/mexfunction.html

merive

Ok, donc tu parlais de ces syntaxes :

1
2
int* p;
int *p;

Honnetement, osef. Suis les guidelines, cela n'a pas d'importance (ou plus precisement, l'important est la coherence).

Et pour les pointeurs intelligents, cela ne pose pas de probleme de les utiliser avec des libs qui utilisent des pointeurs nus. Sauf si la lib a l'ownership de l'objet, tu peux creer une couche sur ta lib pour securiser le code.

1
2
3
void f(int*);
std::unique_ptr<int> p;
f(p.get()); // ok
+0 -0

J'ai commencé à lire le livre recommandé mais dans les exemples donnés les variables sont déclarées comme ceci

1
int variable = 5;

et non avec les {}. Quel est vraiment l'avantage des {} (je n'ai pas réussi à trouver d'explication convaincante)

Merci d'avance pour vos lumières :)

Quel est vraiment l’avantage des {} ?

  • Empêcher les conversions avec perte (narrowing conversion) en jetant une erreur de compilation
  • Forcer l’ordre d’évaluation des expressions¹
  • La généricité dans les constructions:
syntaxe = T() = {} / = T{} () {}
dans la liste d’initialisation non non oui, sauf tableau oui
si constructeur explicite oui oui pour =T{} oui oui
constructeur par défaut oui oui non² oui
construction avec plusieurs paramètres oui² oui oui² oui
initialisation directe³ si pas de ctor non avant C++20 oui non avant C++20 oui
initialisation désignée⁴ (C++20) non oui non oui
construction sur place⁵ non non non oui, sauf si constructeur explicite ou type full-template
définissable dans une condition⁶ oui oui non oui

(Un autre tableau disponible sur le blog de Timur Doumler: https://timur.audio/initialisation-in-c17-the-matrix)

Attention par contre avec les classes qui contiennent un constructeur avec std::initializer_list ; celui-ci est prioritaire si les types sont convertibles. Exemple avec le constructeur de vector vector(std::size_t count, T value):

std::vector<int> v1{5, 3}; // v = {5, 3}
std::vector<int> v1(5, 3); // v = {3,3,3,3,3}

std::vector<std::string> v1{5, "a"}; // {"a","a","a","a","a"}
std::vector<std::string> v1(5, "a"); // {"a","a","a","a","a"}

Une subtile différence existe également avec auto entre les versions des compilateurs qui implémentent ou non c++14. Ceci vient d’une correction tardive dans la norme que les implémenteurs de compilateurs ont appliqués aussi en c++11.

auto i{0};
// gcc < 5 et clang < 3.8 : std::initializer_list<int>
// gcc >= 5 et clang >= 3.8 : int

auto l = {0}; // toujours std::initializer_list<int>

// Je ne sais pas quand Microsoft a introduit le changement dans son compilateur.
// Mais de mémoire, il est le premier à l'avoir fait.

¹ Ordre d’évaluation. Dans l’expression T value(f(ctx), g(ctx)), f(ctx) peut être exécutée après g(ctx), mais dans T value{f(ctx), g(ctx)}, f(ctx) doit être exécutée avant g(ctx).

² Certaines constructions à l’instar de T x(); sont en fait des déclarations de fonctions et non des définitions de variables. Il s’avère que T x(U());, T x(U(y)); ou encore T x(U(y), U(z)); sont aussi des déclarations de prototype. Il est toutefois possible de faire une définition de variable en ajoutant une paire de parenthèses: T x((U(y)), U(z));

³ Direct initialization

struct Coord { int x,y; } // pas de constructeur

Coord c {2,5};

⁴ Designated initializers

struct Coord { int x,y; } // pas de constructeur

Coord c {.x=2, .y=5}; // nom de champ spécifié

⁵ construction sur place

void foo(T);

foo({x,y,z}); // type déduit

⁶ construction dans une condition

if (std::ifstream f{un_fichier}) {
  // blah
}
// équivalent de
{
  std::ifstream f{un_fichier};
  if (f) {
    // blah
  }
}

// l'équivalent pour la boucle while est beaucoup plus moche

// C++17 introduit comme pour `for` une partie initialisation (init-statement) dans le `if`: http://en.cppreference.com/w/cpp/language/if

Historique:

  • 22/08/2021: différence sur l’ordre d’évaluation
  • 11/02/2020: initialisation directe et nommée de C++20
  • 05/03/2017: § pour la déduction de type avec auto
  • 03/12/2016: Pour "construction dans une condition": commentaire sur le bloc d’initialisation ajouté dans le if par c++17.
+5 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte