L’utilisation de std :: vector <std :: shared_ptr > est-elle un antipattern?

Pendant longtemps, j’utilisais std::vector et std::shared_ptr main dans la main. Récemment, j’ai commencé à utiliser std::shared_ptr chaque fois qu’un pointeur sur un object const était nécessaire. Tout cela est OK, car std::shared_ptr peut être transtypé en std::shared_ptr , puis ils partagent le même compteur de références et tout semble naturel.

Mais lorsque j’essaie d’utiliser des constructions telles que std::vector< std::shared_ptr > je rencontre des problèmes. Pour simplifier je vais noter les deux structures:

 template  using SharedPtrVector = std::vector< std::shared_ptr >; template  using SharedConstPtrVector = std::vector< std::shared_ptr >; 

Le problème est que, même si SharedPtrVector et SharedConstPtrVector sont très similaires, SharedConstPtrVector ne peut pas être SharedPtrVector en SharedPtrVector .

Donc, chaque fois que je veux être un const correct et écrire une fonction telle que:

 void f(const SharedConstPtrVector& vec); 

il est impossible de transmettre const SharedPtrVector à f .

J’y pensais beaucoup et j’ai envisagé plusieurs alternatives:

  1. Écrire des fonctions de conversion

     template  SharedConstPtrVector toConst(const SharedPtrVector&); 
  2. Écrivez le code sous forme générique:

     template  void f(const std::vector< std::shared_ptr >& vec); 

    ou

     template  void f(TIterator begin, TIterator end); 
  3. Abandonner l’idée de std::vector< std::shared_ptr >

Le problème avec 1. est la surcharge de calcul et la laideur accrue du code, tandis que 2. donne au code une saveur “tout est un modèle”.

Je suis un programmeur inexpérimenté et je ne veux pas partir dans la mauvaise direction. J’aimerais entendre les conseils de quelqu’un qui a de l’expérience avec ce problème.

Je suggérerais de revoir votre conception en vue d’établir un propriétaire clair de ces objects. C’est l’absence de propriété claire qui amène les gens à utiliser des pointeurs intelligents partagés.

Bjarne Stroustrup recommande d’utiliser des pointeurs intelligents uniquement en dernier recours. Ses recommandations (du meilleur au pire) sont:

  1. Stocke un object par valeur.
  2. Stocke de nombreux objects dans un conteneur par valeur.
  3. Si rien ne fonctionne, utilisez des pointeurs intelligents.

Voir Bjarne Stroustrup – L’essence du C ++: avec des exemples en C ++ 84, C ++ 98, C ++ 11 et C ++ 14 à 0:37:40.

1 Le problème n’est pas lié à shared_ptr<> , mais se produit déjà pour les pointeurs ordinaires:

 template void foo(std::vector); int a,b; std::vector bar={&a,&b}; foo(bar); // no value for ??? works 

2 Le vector> construction vector> est sensiblement seulement si et seulement s’il n’y a pas de propriétaire des objects.

C’est un moyen valable de stocker des objects immuables (et donc thread-safe), un bloc de construction pour un cache de copie sur écriture par élément. Certainement pas un anti-modèle.

si vous insistez pour conserver std::vector vous pouvez essayer de l’encapsuler dans une structure idiomatique de type handle-body.

Cela vous permet de garder un pointeur partagé non const dans une poignée const .