Question

Nous avons une bibliothèque C ++ que nous fournissons à plusieurs clients différents. Récemment, nous avons cessé d'utiliser des pointeurs bruts dans l'interface publique pour plutôt utiliser boost :: sharedptr. Comme vous pouvez le deviner, cela a apporté un énorme avantage, car les clients ne doivent plus se soucier de savoir qui doit supprimer quoi et quand. Lorsque nous avons effectué le changement, je pensais que c'était la bonne chose à faire, mais cela me dérangeait de devoir inclure quelque chose d'une bibliothèque tierce dans notre interface publique - en général, vous évitez ce genre de chose si vous le pouvez. Je l'ai rationalisé en disant que boost faisait pratiquement partie du langage C ++ et que, dans notre cas d'utilisation, le code client et la bibliothèque doivent contenir des pointeurs sur les objets. Cependant, récemment, l'un de nos clients nous a demandé si nous pouvions passer à une classe de pointeur intelligent neutre dans l'interface, car notre bibliothèque les oblige essentiellement à utiliser une version particulière de boost - un point que je comprends et que j'apprécie certainement. Alors maintenant, je me demande quel serait le meilleur plan d’action. J'y ai un peu réfléchi et je me suis demandé si l'on pouvait créer une classe de pointeur intelligent simple contenant simplement un pointeur intelligent boost réel. Mais ensuite, les clients en ajouteraient probablement un dans leur version de boost :: sharedptr, et nous aurions alors trois indicateurs partagés en profondeur - ce qui pourrait être un problème ou non. Quoi qu'il en soit, j'aimerais connaître l'opinion de la communauté sur le meilleur moyen de résoudre ce problème.

Éditer: je parlais à l’origine du transfert de propriété, mais j’aurais dû préciser que le code des deux côtés de la limite de l’API doit contenir un pointeur sur l’objet.

Était-ce utile?

La solution

shared_ptr < > fait partie du langage, à compter de la sortie de TR1. Voir: (TR1)

Autres conseils

Une solution possible consiste à envoyer boost :: shared_ptr avec votre projet. Comme tout est constitué d'en-têtes, cela éviterait à vos clients d'installer les bibliothèques boost manuellement. Vous pouvez utiliser bcp pour obtenir tous les fichiers requis par un bibliothèque boost particulière, y compris les bibliothèques elle-même. Je l’ai fait quand j’avais travaillé pour une entreprise à l’époque et que j’avais besoin de boost::shared_ptr et cela fonctionnait beaucoup.

Si la sémantique est vraiment un transfert de propriété , pourquoi ne pas utiliser auto_ptr puisqu'il s'agit du C ++ standard? En interne, vous pouvez toujours construire vos shared_ptr à partir de auto_ptr, puis en partager la propriété si vous en avez besoin.

Tout d'abord, si vous distribuez votre bibliothèque sous forme de code source plutôt que sous forme de bibliothèque compilée, vous pouvez ignorer cette réponse. Il existe également des problèmes spécifiques à Windows qui peuvent ne pas être pertinents pour d'autres plates-formes.

Personnellement, je pense que vous devriez éviter d'avoir trop de funky c ++ dans l'interface publique de votre bibliothèque, car cela pourrait causer beaucoup de problèmes chez le client.

Je ne sais pas si cela s'applique à votre exemple particulier, mais j'ai personnellement rencontré des problèmes dans lesquels les symboles de la bibliothèque stl que j'ai utilisés entraient en conflit avec ceux de la bibliothèque tierce lorsque j'ai effectué une mise à niveau vers une nouvelle version. Cela signifiait que nous avions des accidents dans des endroits inconnus et que je devais faire beaucoup de manœuvres pour éviter le problème. En fin de compte, je suis resté avec l'ancienne version de la bibliothèque à cause de cela.

Un autre problème que vous pouvez rencontrer est que différents compilateurs c ++ peuvent modifier les mêmes symboles différemment, ce qui signifie que vous devez potentiellement fournir une bibliothèque distincte pour chaque compilateur que vous souhaitez prendre en charge, même s'ils utilisent la même version de Boost. Consultez le livre & Quot; Imperfect C ++ & Quot; pour en discuter.

Dans le monde actuel des différents compilateurs et environnements C ++, je pense que la triste vérité est que vous devez éviter d'avoir autre chose que du C dans votre interface et vous assurer de relier votre bibliothèque de manière dynamique (pour éviter les conflits lorsque vos clients sont liés). La bibliothèque d’exécution de Windows peut être très pénible ici). Vous pouvez toujours utiliser boost et autant de fantaisie c ++ à l'intérieur de votre bibliothèque que vous le souhaitez, car tous vos symboles seront isolés de l'environnement de votre client dans la DLL.

Si vous voulez vraiment avoir des pointeurs intelligents et d'autres fonctionnalités C ++ intéressantes dans l'interface de votre bibliothèque, créez une couche de commodité pour laquelle vous distribuez le code source. Cela garantira qu'il est toujours compilé dans l'environnement du client. Cette interface appelle ensuite vos fonctions C exposées de manière intelligente. Je ne pense pas que ce soit une bonne idée d'utiliser boost dans cette couche, car cela forcera vos clients à l'adopter même s'ils ne veulent pas, mais il est facile de la remplacer ou de trouver une autre solution puisque cette couche est distribuée en tant que source. code.

Une autre fonctionnalité intéressante est qu'il est généralement plus facile d'appeler des fonctions C dans une dll que des fonctions c ++ avec un nom étrange si vous souhaitez exposer votre bibliothèque à d'autres langages que le C / C ++.

Cette approche vous complique la vie à bien des égards, mais c’est une façon de réduire les risques que les utilisateurs évitent votre bibliothèque, car il n’était tout simplement pas possible de faire le lien avec leur propre code.

Ceci est C ++. Vous savez, vous pouvez modéliser la classe d'interface sur l'implémentation de pointeur partagé.

C’est une question intéressante que je pose depuis un certain temps. Est-ce que vous forcez vos utilisateurs dans la bibliothèque que vous fournissez, ou les laissez-vous décider du meilleur de leur projet? Comme toujours, la question est de savoir ce que vous proposez et ce que vous attendez de l'utilisateur.

Si vous utilisez des pointeurs bruts, vous autorisez toutes sortes de possibilités. Le code utilisateur peut utiliser un pointeur brut, le stocker dans std :: auto_ptr, shared_ptr (que ce soit boost ou TR1) ou leur version homebrewed d'un pointeur intelligent. Mais cela peut également causer des problèmes à l’utilisateur s’il oublie de libérer de la mémoire, ce qui nécessite un peu plus de code de la part des utilisateurs s’ils veulent juste une création temporaire pour un appel de méthode (si vous fournissez des pointeurs bruts, ils devront stocker le pointeur dans une variable de pointeur non temporaire [éventuellement intelligente]).

Maintenant, si vous utilisez un pointeur intelligent, vous forcez votre solution vers l'utilisateur. S'ils envisagent d'utiliser leur propre version d'un pointeur intelligent (par exemple, vous utilisez boost :: shared_ptr et qu'ils veulent std :: tr1 :: shared_ptr), ils ne sont plus autorisés à l'utiliser s'ils fonctionnent avec votre interface. Quel que soit le pointeur intelligent que vous choisissez (en plus de std :: auto_ptr qui est spécial), vous forcez non seulement une solution, mais également les problèmes qu’elle pose.

Si votre utilisateur dispose d'une application multithread et que votre solution n'est pas thread-safe, l'utilisateur est lié à une solution non sécurisée. Si, en revanche, le pointeur intelligent est sécurisé pour le thread mais qu'il entraîne des coûts de verrouillage, ceux-ci sont supportés par vos utilisateurs, même s'ils travaillent dans une application multithread. Si vous compilez votre bibliothèque (pas uniquement un entête lib), vous forcez non seulement un type de pointeur intelligent, mais également une version particulière de celui-ci, car toute modification apportée à la bibliothèque de pointeurs intelligents rompra la compatibilité de votre code.

En remarque, boost :: shared_ptr (boost 1.33+) est thread safe dans la plupart des situations, et il utilise une implémentation sans verrouillage dans de nombreuses plates-formes. Quoi qu'il en soit, cela devrait vous donner une idée de ce que vous devriez considérer.

Enfin, vous devez considérer que vous obligez non seulement l'utilisateur à utiliser votre type de pointeur intelligent, mais également la même version de celui-ci. Si vous compilez votre bibliothèque avec une version particulière de boost, l'utilisateur est lié à cette implémentation particulière o

Vous pouvez utiliser l'utilitaire boost copy . pour créer une version personnalisée de boost contenant uniquement la classe de pointeur intelligent. Étant donné que la classe de pointeur intelligent est une bibliothèque contenant uniquement des en-têtes, vous devriez inclure quelques en-têtes que vous pourriez inclure avec votre bibliothèque.

l'introduction de boost :: shared_ptr oblige votre client à utiliser boost. pour certaines personnes, il s'agit d'un problème mineur.

Il oblige également vos clients à utiliser le même compilateur que celui utilisé par votre bibliothèque, si celle-ci est distribuée sous forme de fichier binaire compilé. ou, si votre bibliothèque est distribuée dans le code source, les clients doivent s'en tenir à leur propre choix du compilateur utilisé pour compiler votre bibliothèque. Ce n'est pas un problème mineur pour tout projet de taille considérable.

Utilisez auto_ptr ou utilisez une interface C. Forcer des librairies C ++ dans votre interface est toujours moche, tue toute chance d'être multiplate-forme, et provoque un cauchemar de maintenance pour les clients avec un & Quot;

Dès que C ++ 0x est suffisamment intégré pour vos clients, passez à std::shared_ptr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top