visual studio microsoft español descargar community c++ api boost shared-ptr

c++ - microsoft - visual studio installer



Uso de boost:: shared_ptr en la interfaz pública de una biblioteca (10)

En primer lugar, si distribuye su biblioteca como código fuente en lugar de como una biblioteca compilada, puede ignorar esta respuesta. También hay algunos problemas específicos de Windows que pueden no ser relevantes para otras plataformas.

Personalmente, creo que debes evitar tener demasiado funky c ++ en la interfaz pública de tu biblioteca, ya que puede causar muchos problemas al cliente.

No estoy seguro de qué tan aplicable es esto para su ejemplo particular, pero personalmente me he encontrado con problemas en los que los símbolos de la biblioteca stl que utilicé entraron en conflicto con los de la biblioteca de terceros cuando actualicé a una nueva versión. Esto significa que tuvimos accidentes en lugares extraños y tuve que hacer muchos trucos para evitar el problema. Al final, me quedé con la versión anterior de la biblioteca debido a esto.

Otro problema con el que se puede encontrar es que los diferentes compiladores de c ++ pueden dividir los mismos símbolos de forma diferente, lo que significa que posiblemente necesite proporcionar una biblioteca separada para cada compilador que desee admitir, incluso si utilizan la misma versión de Boost. Vea el libro "C ++ imperfecto" para una discusión sobre esto.

En el mundo actual de diferentes compiladores y entornos de C ++, creo que la triste verdad es que debes evitar tener cualquier cosa que no sea C en tu interfaz y asegurarte de vincular tu biblioteca dinámicamente (para evitar conflictos al vincular los enlaces de tus clientes a tu biblioteca de Windows runtime puede ser un verdadero dolor aquí). Todavía puede usar Boost y C ++ en el interior de su biblioteca como desee, ya que todos sus símbolos estarán aislados del entorno de sus clientes en el dll.

Si realmente desea tener punteros inteligentes y otra funcionalidad agradable de C ++ en la interfaz de su biblioteca, cree una capa conveniente para distribuir el código fuente. Esto asegurará que siempre esté compilado en el entorno del cliente. Esta interfaz luego llama a sus funciones C expuestas de manera inteligente. No creo que sea una buena idea utilizar boost en esa capa, ya que obligará a sus clientes a adoptarla incluso si no quieren, sin embargo, es fácil reemplazarla o encontrar otra solución, ya que esa capa se distribuye como fuente código.

Otra buena característica es que, en general, es más fácil llamar a las funciones C en un dll que a las funciones de C ++ con un extraño cambio de nombre si desea exponer su biblioteca a otros lenguajes además de C / C ++.

Este enfoque definitivamente hace que su vida sea más complicada de muchas maneras, pero es una forma de evitar que las personas eviten su biblioteca porque simplemente no era posible vincularse exitosamente con su propio código.

Tenemos una biblioteca en C ++ que brindamos a varios clientes diferentes. Recientemente, hicimos el cambio de usar punteros sin formato en la interfaz pública a usar boost :: sharedptr en su lugar. Esto ha proporcionado un enorme beneficio, como se puede adivinar, en que ahora los clientes ya no tienen que preocuparse por quién necesita eliminar qué y cuándo. Cuando hicimos el cambio creí que era lo correcto, pero me molestaba tener que incluir algo de una biblioteca de terceros en nuestra interfaz pública; en general, evitas ese tipo de cosas si puedes. Lo racionalicé que el impulso era prácticamente parte del lenguaje C ++ ahora, y nuestro caso de uso requiere que tanto el código del cliente como la biblioteca contengan punteros a los objetos. Sin embargo, recientemente, uno de nuestros clientes nos ha preguntado si podríamos cambiar al uso de una clase de puntero inteligente neutral en la interfaz, porque nuestra biblioteca básicamente los está forzando a una versión particular de refuerzo, un punto que ciertamente entiendo y aprecio. Entonces ahora me pregunto cuál sería el mejor curso de acción. Lo he pensado un poco, y me pregunté si crearía una clase de puntero inteligente simple que simplemente tuviera un puntero inteligente real. Pero luego los clientes probablemente incluirían inmediatamente uno de esos en su sabor de boost :: sharedptr, y luego tendríamos tres punteros compartidos de profundidad, lo que podría ser un problema, o podría no serlo. De todos modos, me gustaría escuchar algunas opiniones de la comunidad sobre la mejor manera de resolver este problema.

Editar: Originalmente dije transferencia de propiedad, pero debería haber especificado que el código en ambos lados del límite API necesita mantener un puntero al objeto.


Esta es una pregunta interesante que he tenido durante algún tiempo. ¿Obliga a los usuarios a acceder a la biblioteca que les proporcione o les permite decidir qué es lo mejor en su proyecto? Como siempre, la pregunta es qué está ofreciendo y qué necesita del usuario.

Si usa punteros sin procesar, permite todo tipo de posibilidades. El código de usuario puede usar un puntero sin formato, almacenarlo en std :: auto_ptr, shared_ptr (ya sea boost o TR1), o su versión casera de un puntero inteligente. Pero esto también puede meter al usuario en problemas si se olvidan de liberar la memoria, y requiere un poco más de código en su lado si solo quieren una llamada temporal creada para un método (si proporciona punteros crudos, tendrán que almacenar el puntero en una variable de puntero no temporal [posiblemente inteligente]).

Ahora, si usa un puntero inteligente, está forzando su solución al usuario. Si planean usar su propia versión de un puntero inteligente (digamos que usas boost :: shared_ptr y quieren std :: tr1 :: shared_ptr), ya no pueden usarlo si trabajan con tu interfaz. Independientemente del puntero inteligente que elija (además de std :: auto_ptr que es especial), no solo está forzando una solución, sino también los problemas que tiene.

Si su usuario tiene una aplicación multiproceso y su solución no es segura para subprocesos, el usuario está obligado a una solución insegura. Si, por otro lado, el puntero inteligente es seguro para subprocesos pero implica costos de bloqueo, esos costos se envían a sus usuarios incluso si funcionan en una aplicación multiproceso. Si compila su biblioteca (no solo un encabezado lib), está forzando no solo un tipo de puntero inteligente, sino también una versión particular del mismo, ya que cualquier cambio en la biblioteca del puntero inteligente romperá la compatibilidad de su código.

Como nota al margen, boost :: shared_ptr (boost 1.33+) es seguro para subprocesos en la mayoría de las situaciones, y utiliza una implementación sin bloqueo en muchas plataformas. De todos modos, esto debería darte una idea de las cosas que debes considerar.

Finalmente, debe considerar que no solo está obligando al usuario a usar su tipo de puntero inteligente, sino también la misma versión del mismo. Si compila su lib contra una versión particular de boost, el usuario está obligado a esa implementación particular o


Esto es C ++. Ya sabes, podrías moldear la clase de interfaz sobre la implementación del puntero compartido.


Puede usar la utilidad de copia de refuerzo para crear una versión personalizada de boost que solo tenga la clase de puntero inteligente. Dado que la clase de puntero inteligente es una biblioteca de solo encabezado, esto debería generar algunos encabezados que podría incluir con su biblioteca.


Si la semántica es realmente la transferencia de propiedad , ¿por qué no utilizar auto_ptr ya que es estándar C ++? Internamente, puede construir su shared_ptr desde el auto_ptr y luego tener la propiedad compartida si la necesita.


shared_ptr <> es parte del lenguaje, a partir del lanzamiento de TR1. Ver: (TR1)



Una posible solución es enviar boost :: shared_ptr con su proyecto. Como todo se compone de encabezados, esto liberaría a sus clientes de tener que instalar las bibliotecas de impulso manualmente. Puede usar bcp para obtener todos los archivos necesarios para una biblioteca de impulso en particular, incluidas las bibliotecas. Lo hice cuando trabajaba para una empresa en aquel entonces y necesitaba boost::shared_ptr y en realidad funcionó en gran medida.


Use auto_ptr o pegue a una interfaz C. Forzar bibliotecas de C ++ en su interfaz siempre es feo, elimina cualquier posibilidad de ser multiplataforma y causa una pesadilla de mantenimiento para clientes con diferentes configuraciones de "flujo descendente".

Tan pronto como C ++ 0x sea lo suficientemente convencional para sus clientes, cambie a std::shared_ptr .


introduciendo boost :: shared_ptr obliga a tu cliente a usar boost. para algunas personas, este es un problema menor.

también obliga a sus clientes a usar el mismo compilador que usa su lib, si su lib se distribuye como binario compilado. o, si su biblioteca se distribuye en código fuente, los clientes tienen que apegarse a su propia elección del compilador utilizado para compilar su lib. esto no es un problema menor para cualquier proyecto de tamaño considerable.