Outils d'utilisateurs

Outils du Site


pointeurs_style_c

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

pointeurs_style_c [2016/04/26 17:18]
gbdivers créée
pointeurs_style_c [2016/04/26 18:24] (Version actuelle)
gbdivers
Ligne 24: Ligne 24:
 void f(...);  // quoi mettre ici ? void f(...);  // quoi mettre ici ?
  
-int i;+int* pi;
 f(~i~); f(~i~);
  
 std::unique_ptr<int> upi; std::unique_ptr<int> upi;
-f(~pi~);+f(~upi~);
  
  
Ligne 209: Ligne 209:
  
  
 +==== Fonction generique ====
 +
 +Utilisation de template pour passer les indirections.
 +
 +<code cpp>
 +template<class T>
 +void f(T const& value);
 +
 +int* pi;
 +f(pi);
 +
 +std::unique_ptr<int> upi;
 +f(upi);
 +
 +
 +std::shared_ptr<int> spi;
 +f(spi);
 +</code>
 +
 +**Probleme 1** : acces aux objets. Selon le type d'indirection (ref vs pointeur), acces via l'operateur ''.'' ou ''->''. Besoin de surcharger selon les 2 cas.
 +
 +<code cpp>
 +template<class T>
 +void f_ref(T const& value) {  // T est une ref
 +    value.do_something();
 +}
 +
 +template<class T>
 +void f_ptr(T const& value) {  // T est un pointeur
 +    value->do_something();
 +}
 +</code>
 +
 +**Probleme 2** : semantique des pointeurs = peut etre nullptr. Donc necessite de verifier les acces avant utilisation. Pas necessaire avec ref.
 +
 +<code cpp>
 +template<class T>
 +void f_ref(T const& value) {  // T est une ref
 +    value.do_something();
 +}
 +
 +template<class T>
 +void f_ptr(T const& value) {  // T est un pointeur
 +    assert(value);            // check ptr
 +    value->do_something();
 +}
 +</code>
 +
 +**Probleme 3** : gerer l'ownership. Certains n'ont pas l'ownership (ref, raw ptr, weak_ptr, etc) et d'autre oui (unique_ptr, shared_ptr, etc). Difficile de gerer cela avec les template.
 +
 +Par exemple, si on passe un weak_ptr, il faut locker avant d'utiliser.
 +
 +<code cpp>
 +template<class T>
 +void f_ptr(T const& sp) {  // T est un weak_ptr
 +    auto sp { wp.lock() }; // lock en shared_ptr
 +    assert(sp);            // check ptr
 +    sp->do_something();
 +}
 +</code>
 +
 +Autre exemple, si on veut transmettre l'ownership a une fonction :
 +
 +<code cpp>
 +std::unique_ptr<int> up;
 +f(std::move(up));  // on n'a plus besoin de up ensuite
 +</code>
 +
 +**Conclusion** : generique, mais trop de cas particulier a gerer. (+ tous les libs possible)
 +
 +==== Les references comme parametre universel ====
 +
 +Conserver qu'une seule forme : passage par reference.
 +
 +<code cpp>
 +// T est un objet, pas une indirection. Template ou non
 +
 +void f(T const& ref);  // objet non mutable
 +void g(T& ref);        // objet mutable
 +</code>
 +
 +Reference apporte les garanties : que l'objet est valide et que la fonction n'a pas l'ownership. Rien a tester dans la fonction et 1 syntaxe a ecrire.
 +
 +Ensuite, creer des adaptateurs pour chaque type d'indirection, via lambda.
 +
 +Pour une valeur :
 +
 +<code cpp>
 +int i;
 +f(i); // appel direct
 +</code>
 +
 +Pour shared_ptr :
 +
 +<code cpp>
 +std::shared_ptr<int> spi;
 +
 +f(*spi);
 +
 +[spi](){ f(*spi); }; // asynchrone
 +</code>
 +
 +Pour weak_ptr :
 +
 +<code cpp>
 +std::weak_ptr<int> wpi;
 +
 +[spi = wpi.lock()](){ f(*spi); }; // lock lors de la capture
 +
 +[wpi](){ auto spi { wpi.lock(); if (spi) { f(*spi); } }; // lock lors de l'appel a f
 +</code>
 +
 +Pour unique_ptr :
 +
 +<code cpp>
 +std::unique_ptr<int> upi;
 +
 +f(*upi);  // appel direct
 +
 +[p = std::move(upi)](){ f(*p); }; // asynchrone
 +</code>
 +
 +Pour raw ptr :
 +
 +<code cpp>
 +int* pi;
 +
 +if (pi) { f(*pi); }  // appel direct... dangling possible
 +
 +[pi](){ if (pi) { f(*pi); } }; // asynchrone... dangling possible
 +</code>
 +
 +Not safe, risque de dangling.
 +
 +etc.
 +
 +==== Cas particulier des pointeurs nus ====
 +
 +Raw ptr ont semantique "peut etre nullptr". Generalement, le traitement effectue par f pourra se decomponser en 2 partie strictement distincte, selon si nullptr ou non. Il est donc dans ce cas possible de gerer le cas de nullptr en dehors de f et d'utiliser les references (ne peut pas etre nullptr).
 +
 +<code cpp>
 +void f_nullptr();
 +void f_notnull(T const& ref);
 +
 +int* pi;
 +if (pi) {
 +    f_notnull(pi);
 +} else {
 +    f_nullptr();
 +}
 +</code>
 +
 +Pas besoin de passer directement un pointeur, ref est "universel". (les cas ou on doit passer un pointeur doivent rester rare).
 +    
  
pointeurs_style_c.1461683881.txt.gz · Dernière modification: 2016/04/26 17:18 par gbdivers