Débuter en C++

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

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 -0

Cette réponse a aidé l'auteur du sujet

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 :)

+3 -0

membres commencent par _

Je ne suis pas sûr que cette convention soit recommandable car les nom de variables / attributs et nom de classes commençant par un "_" ou "__" doivent être évités pour être utilisé par le compilateur ou l'implémentation de la STL.

Édité par victorlevasseur

+1 -0
Auteur du sujet

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

+0 -0

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
Auteur du sujet

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 :)

+0 -0

Cette réponse a aidé l'auteur du sujet

Quel est vraiment l'avantage des {} ?

  • Empêcher les conversions avec perte (narrowing conversion) en jetant une erreur de compilation
  • La généricité dans les constructions:
syntaxe = () {}
dans la liste d'initialisation non oui, sauf tableau oui
si constructeur explicite non oui oui
constructeur par défaut = T() ou = {} non¹ oui
construction avec plusieurs paramètres = T(...) ou = {...} oui¹ oui
initialisation directe² si pas de ctor = {...} non oui
construction sur place³ non T(...) oui, sauf si constructeur explicite ou type full-template
définissable dans une condition⁴ oui non oui

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):

1
2
3
4
5
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"}

¹ 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));

² directe-list-initialisation

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

Coord c {2,5};

³ construction sur place

1
2
3
void foo(T);

foo({x,y,z});

⁴ construction dans une condition

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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

Édité par jo_link_noir

+3 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

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