2011-11-23 10 views
5

Estoy en proceso de transferir algún código de Objective C a C++. No estoy tan familiarizado con los patrones de diseño C++ como con el Objetivo C. En el mundo Cocoa, existe el patrón muy común de escribir un método de fábrica que devuelve un objeto "liberado automáticamente". Algo tan simple como:Objective C "liberación automática" en C++: ¿forma estándar de controlar la duración del objeto?

- (MyClass *)load { 

    MyClass* obj = [[MyClass alloc] init]; 
    return [obj autorelease]; 
} 

Esto es simple y fácil de entender. El método posee la memoria que asigna, pero puede devolvérselo a la persona que llama, al tiempo que renuncia a la propiedad. No tiene que saber o preocuparse por lo que hace la persona que llama con esa memoria. Si lo conserva, el objeto sobrevivirá. Si se ignora por completo, la memoria se liberará en algún momento después de que se desenrolla la pila de llamadas actual.

Me estoy acercando a esto con cierta inquietud en C++, porque su entorno no contado no parece tener nada tan limpio como autorelease, o cualquier tipo de política de propiedad que esté tan bien definida como las del Marcos de cacao. ¿Cuáles son las mejores prácticas para este tipo de patrón en C++?

Conozco auto_ptr, pero también existen muchas preocupaciones con respecto a su uso, y parece tener demasiadas deficiencias para ser tan omnipresente como autorelease (semántica de copia extraña, no admite matrices, incompatibilidad con contenedores STL , etc.)

Los punteros inteligentes Boost también son un candidato obvio, y algunos incluso implementan su propio recuento de referencias. Me parece un poco extraño tener que apoyarme en una biblioteca de terceros para algo tan mundano.

Otra opción que apesta a C sería solo no liberar la memoria devuelta, pero indicar a través de la convención de nombres comúnmente adoptada que la persona que llama ahora es propietaria del objeto devuelto. Esto parece un poco arcaico, y es propenso a fugas invisibles si la persona que llama accidentalmente ignora el valor de retorno.

+2

"Me parece un poco extraño tener que apoyarme en una biblioteca de terceros por algo tan mundano". Acostumbrarse a él. Así es como se hacen las cosas en C++: encuentras bibliotecas que hacen lo que necesitas y las usas. La propiedad de la memoria no es sintáctica en C++; es * siempre * manual. –

Respuesta

8

las "mejores prácticas" en el mundo C++ 03 (es decir, pre-C++ 11) son una de dos cosas:

  1. hacer nada. Esto es esencialmente propiedad de la memoria por suposición/convención. Si una función devuelve un puntero, debe saber a quién pertenece. Usualmente, la documentación te dirá. No hay una sintaxis específica para la propiedad de la memoria o para transferir la propiedad.

    Así es como desafortunadamente una gran cantidad de código C++ gestiona la memoria. Puede funcionar, siempre que todos sepan qué deberían estar haciendo y quién es responsable de qué.

  2. Utilice algún tipo de puntero inteligente. std::auto_ptr es extraño, pero es tan liviano como se obtiene en C++ 03. No, no puede pegarlos en contenedores estándar, pero define un patrón específico de propiedad.Un boost::shared_ptr es más efectivo y es más útil en muchos otros lugares.

C++ 11 ofertas std::unique_ptr, que es esencialmente un "fijo" auto_ptr. Se basa en las características del lenguaje C++ 11 (movimiento de objetos), por lo que no puede simplemente escribir uno en C++ 03. Puede almacenarlos en contenedores estándar y todo. Pero no puedes simplemente pasarlos. Como su nombre indica, son unique: solo puede existir uno de ellos que apunte a ese objeto. Cuando se destruye ese unique_ptr, elimina el objeto al que hace referencia.

Puede transferir propiedad de un unique_ptr solo regalándolo. Es decir, no puede compartir la propiedad de. Puede devolver la propiedad, lo que significa que la persona que llama ahora la posee. Puede pasar la propiedad a otra función, lo que significa que esa función la posee. Pero no hay dos entidades que puedan poseer un objeto a través de unique_ptr.

unique_ptr sería el método preferido para manejar una función como esta. Si el usuario desea almacenarlo de forma no exclusiva, puede liberarlo en un std::shared_ptr (que también se adoptó en C++ 11).

3

Me gustaría ver el shared_ptr en impulso.

El mundo C++ tiene que ver con las bibliotecas. Debido a que nadie posee C++ (a diferencia de Objective-C), crece a medida que la comunidad ve la necesidad.

2

Bueno, la mayor parte C++ - como opción está utilizando punteros inteligentes ..

Por lo que leo, punteros recuento de referencias son la mejor opción, en el C++ 11 estándar puede utilizar el shared_ptr

Cuestiones relacionadas