Pregunta

Tenemos una biblioteca de C++ que ofrecemos a varios clientes diferentes.Recientemente hemos realizado el cambio de uso de raw punteros en la interfaz pública para el uso de boost::sharedptr lugar.Esto ha proporcionado un beneficio enorme, como se puede adivinar, en que ahora los clientes ya no tienen que preocuparse acerca de quién se debe eliminar el qué y el cuándo.Cuando hemos hecho el cambio, yo creía que era la cosa correcta a hacer, pero me molestó que había que incluir algo de una librería de terceros en nuestra interfaz pública - en general, a evitar ese tipo de cosas, si puede.Razoné que impulso fue prácticamente parte del lenguaje C++ ahora, y en nuestro caso de uso requiere que tanto el código de cliente y el de la biblioteca de mantener los punteros a los objetos.Sin embargo, recientemente uno de nuestros clientes nos pidió si podíamos pasar a utilizar un neutral puntero inteligente de la clase en la interfaz, debido a que nuestra biblioteca es, esencialmente, obligándolos a una versión particular del aumento de un punto que yo sin duda, entender y apreciar.Así que ahora me estoy preguntando cuál es el mejor curso de acción podría ser.Lo he pensado un poco, y se preguntó acerca de la creación de un simple puntero inteligente de la clase que simplemente a cabo un verdadero impulso puntero inteligente.Pero a continuación, los clientes probablemente inmediatamente cosas una de esas en su sabor de boost::sharedptr, y entonces estaríamos tres compartido punteros profunda de lo que podría ser un problema, o puede que no.De todos modos, me gustaría escuchar algunas opiniones de la comunidad acerca de la mejor manera de resolver este problema.

Editar:Originalmente me dijo que la transferencia de propiedad, pero tendría que haber especificado que el código en ambos lados de la API de límite de la necesidad de mantener un puntero al objeto.

¿Fue útil?

Solución

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

Otros consejos

Una posible solución es enviar boost::shared_ptr con su proyecto.Como todo consta de los encabezados, esto podría liberar a sus clientes de tener que instalar el impulso de las bibliotecas de forma manual.Puede utilizar bcp para obtener todos los archivos que necesita un estímulo particular de la biblioteca, incluyendo las bibliotecas de sí mismo.Lo hice cuando trabajaba para una empresa y necesita boost::shared_ptr y es que en realidad trabajaba mucho.

Si la semántica es realmente transferencia de propiedad , ¿por qué no usar auto_ptr ya que es C ++ estándar? Internamente, aún puede construir sus shared_ptr a partir de auto_ptr y luego compartir la propiedad si lo necesita.

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 debe evitar tener demasiados c ++ en la interfaz pública de su biblioteca, ya que puede causar muchos problemas en el cliente.

No estoy seguro de cuán aplicable es esto a su ejemplo particular, pero personalmente he tenido problemas en los que los símbolos de la biblioteca stl que utilicé entraban 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 diferentes compiladores de c ++ pueden manipular los mismos símbolos de manera diferente, lo que significa que posiblemente necesite proporcionar una biblioteca separada para cada compilador que desee admitir, incluso si usan la misma versión de Boost. Mira el libro & Quot; Imperfect C ++ & Quot; para una discusión sobre esto.

En el mundo actual de diferentes compiladores y entornos de C ++, creo que la triste verdad es que debe evitar tener otra cosa que no sea C en su interfaz y asegúrese de vincular su biblioteca de forma dinámica (para evitar conflictos al vincular sus clientes, su biblioteca, La biblioteca de tiempo de ejecución de Windows puede ser un verdadero dolor aquí). Todavía puede usar boost y tantos C ++ sofisticados 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 otras funciones agradables de C ++ en la interfaz de su biblioteca, cree una capa conveniente para la que distribuya el código fuente. Esto asegurará que siempre se compila en el entorno del cliente. Esta interfaz llama a sus funciones C expuestas de manera inteligente. No creo que sea una buena idea usar boost en esa capa, ya que obligará a sus clientes a adoptarlo incluso si no lo desean, sin embargo, es fácil reemplazarlo 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 de C en un archivo dll que a las funciones de c ++ con un extraño cambio de nombre si desea exponer su biblioteca a otros idiomas que no sean C / C ++.

Este enfoque definitivamente hace que su vida sea más complicada de muchas maneras, pero es una forma de hacer que sea menos probable que las personas eviten su biblioteca porque simplemente no era posible vincular con éxito con su propio código.

Esto es C ++. Sabes, puedes modelar la clase de interfaz sobre la implementación del puntero compartido.

Esta es una pregunta interesante que he tenido por algún tiempo. ¿Forzas a tus usuarios a ingresar a la biblioteca que proporciones o les dejas decidir qué es lo mejor en su proyecto? Como siempre, la pregunta es qué ofrece y qué requiere 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 ocasionar problemas al usuario si se olvida de liberar la memoria, y requiere un poco más de código si solo desea que se cree una temporal para una llamada al método (si proporciona punteros sin procesar, tendrán que almacenar el código 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 se les permite usarlo si funcionan con tu interfaz. Independientemente del puntero inteligente que decida (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 incurre en costos de bloqueo, esos costos se transfieren a sus usuarios incluso si trabajan en una aplicación multiproceso. Si compila su biblioteca (no solo una biblioteca de encabezado), está forzando no solo un tipo de puntero inteligente, sino también una versión particular de la misma, ya que cualquier cambio en la biblioteca de 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 darle una idea de las cosas que debe considerar.

Finalmente, debe tener en cuenta 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

Puede utilizar la utilidad boost copy para construir una versión personalizada de boost que solo tenía 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.

la introducción de boost :: shared_ptr obliga a su 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 atenerse a su propia elección del compilador utilizado para compilar su lib. Esto no es un problema menor para ningún proyecto de tamaño considerable.

Use auto_ptr o quédese con una interfaz C. Forzar las bibliotecas de C ++ en su interfaz siempre es feo, elimina cualquier posibilidad de ser multiplataforma y provoca una pesadilla de mantenimiento para los clientes con diferentes & Quot; downstream & Quot; configuraciones.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top