c++ - ¿Separe un puntero de un shared_ptr?
boost shared-ptr (5)
Posible duplicado:
¿Cómo liberar el puntero de boost :: shared_ptr?
Una función de mi interfaz devuelve un puntero a un objeto. Se supone que el usuario se apropia de ese objeto. No quiero devolver un Boost.shared_ptr, porque no quiero obligar a los clientes a usar boost. Internamente, sin embargo, me gustaría almacenar el puntero en un shared_ptr para evitar fugas de memoria en caso de excepciones, etc. Parece que no hay forma de separar un puntero de un puntero compartido. Alguna idea aqui?
Se supone que el usuario se apropia de ese objeto. No quiero devolver un Boost.shared_ptr,
shared_ptr
expresa la propiedad compartida , y desea que su interfaz exprese la transferencia de propiedad. std::auto_ptr
sería así más aplicable aquí.
Internamente, sin embargo, me gustaría almacenar el puntero en un shared_ptr para evitar fugas de memoria en caso de excepciones
De nuevo, shared_ptr
puede no ser la mejor herramienta para ese trabajo. Para evitar fugas en el caso de excepciones, scoped_ptr
o auto_ptr
se scoped_ptr
mejor.
Como James ha cubierto bien, no se puede separar un puntero compartido.
¿Necesita varios propietarios internamente o está transfiriendo la propiedad de su clase al cliente? En ese caso, un std::auto_ptr
podría encajar en la factura.
Si le preocupa la sorprendente semántica de std::auto_ptr
, puede mantenerla internamente en boost::scoped_ptr
, y separarla en el punto en que la distribuye, dejando que el cliente la elimine o la almacene manualmente. en su propio puntero inteligente.
Si tiene varios propietarios de su lado, podría usar un conteo intrusivo. Internamente, puede usar boost::intrusive__ptr
, pero pase el puntero sin formato a la interfaz. El cliente puede entonces trabajar manualmente con recuentos de ref, o almacenarlo en un boost::intrusive_ptr
(pero no los hace depender de él)
Utilice un shared_ptr
para un scoped_ptr
para el recurso ( shared_ptr<scoped_ptr<Resource>>
). De esta manera obtendrá el shared_ptr
de referencias de shared_ptr
, que destruirá automáticamente el recurso si y solo si todavía está adjunto al scoped_ptr
. Pero puede desconectar el scoped_ptr
cuando esté listo para scoped_ptr
la propiedad.
siempre hay una manera :-)
De hecho, hay una razón por la cual no proporcionan un método de liberación (), pero no es imposible crear uno. Crea tu propio eliminador. Algo en la línea de (en realidad no compiló el código, pero esta es la noción general):
template <typename T>
class release_deleter{
public:
release_deleter() : released_(new some_atomic_bool(false)){}
void release() {released_->set(true);}
void operator()(T* ptr){if(!released_->get()) delete ptr;}
private:
shared_ptr<some_atomic_bool> released_;
}
..
shared_ptr<some_type> ptr(new some_type, release_deleter<some_type>());
..
release_deleter<some_type>* deleter = get_deleter<release_deleter<some_type>>(ptr);
deleter->release();
some_type* released_ptr = ptr.get();
Lo que estás buscando es una función de release
; shared_ptr
no tiene una función de liberación. Según el manual de Boost :
P. ¿Por qué shared_ptr no proporciona una función de liberación ()?
R. shared_ptr no puede revelar la propiedad a menos que sea única () porque la otra copia seguirá destruyendo el objeto.
Considerar:
shared_ptr<int> a(new int);
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.
Además, el puntero devuelto por la versión () sería difícil de desasignar confiablemente, ya que la fuente shared_ptr podría haberse creado con un eliminador personalizado.
Dos opciones que podrías considerar:
- Puede usar
std::tr1::shared_ptr
, lo que requeriría que sus usuarios usen una implementación de biblioteca C ++ que soporte TR1 o que use Boost; al menos esto les daría la opción entre los dos. - Podría implementar su propio puntero compartido
boost::shared_ptr
y usarlo en sus interfaces externas.
También puede ver la discusión en esta pregunta sobre el uso de boost :: shared_ptr en la interfaz pública de una biblioteca .