Pregunta

Puede impulsar :: shared_ptr liberar el puntero almacenado sin eliminarlo?

Puedo ver que no existe función de liberación en la documentación, también en el FAQ se explica por qué no proporciona función de liberación, algo así como que la liberación no se puede hacer sobre los punteros que no son únicos. Mis punteros son únicos. ¿Cómo puedo liberar mis punteros? O que potencian la clase puntero inteligente de usar que permitirá que la liberación del puntero? Espero que no voy a decir el uso auto_ptr:)

¿Fue útil?

Solución

Es necesario utilizar un Deleter que puede solicitar no borrar el puntero subyacente.

ver este respuesta (que ha sido marcado como duplicado de esta pregunta) para obtener más información.

Otros consejos

No lo haga. Preguntas entrada de impulso:

  

Q . ¿Por qué no shared_ptr proporcionar una función de desbloqueo ()?

     

A . shared_ptr no puede ceder la propiedad a menos que sea único (), ya que la otra copia todavía va a destruir el objeto.

     

Considere lo siguiente:

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 liberación () sería difícil de anular la planificación fiable, ya que la fuente de shared_ptr pudo haber sido creado con un Deleter personalizado.

Por lo tanto, esto sería seguro en caso de que sea el único caso shared_ptr que apuntan a su objeto (cuando único () devuelve verdadero) y el objeto no requiere una Deleter especial. Todavía me pregunto su diseño, si se ha utilizado una función tal .release ().

Se puede usar Deleter falso. Entonces punteros no se eliminarán realidad.

struct NullDeleter {template<typename T> void operator()(T*) {} };

// pp of type some_t defined somewhere
boost::shared_ptr<some_t> x(pp, NullDeleter() );

Los niños, no hacer esto en casa:

// set smarty to point to nothing
// returns old(smarty.get())
// caller is responsible for the returned pointer (careful)
template <typename T>
T* release (shared_ptr<T>& smarty) {
    // sanity check:
    assert (smarty.unique());
    // only one owner (please don't play games with weak_ptr in another thread)
    // would want to check the total count (shared+weak) here

    // save the pointer:
    T *raw = &*smarty;
    // at this point smarty owns raw, can't return it

    try {
        // an exception here would be quite unpleasant

        // now smash smarty:
        new (&smarty) shared_ptr<T> ();
        // REALLY: don't do it!
        // the behaviour is not defined!
        // in practice: at least a memory leak!
    } catch (...) {
        // there is no shared_ptr<T> in smarty zombie now
        // can't fix it at this point:
        // the only fix would be to retry, and it would probably throw again
        // sorry, can't do anything
        abort ();
    }
    // smarty is a fresh shared_ptr<T> that doesn't own raw

    // at this point, nobody owns raw, can return it
    return raw;
}

Ahora, ¿hay una manera de comprobar si el recuento total de los propietarios para el recuento de ref es> 1

Para permitir que el punto puntero a nada nuevo, puede llamar shared_ptr::reset().

Sin embargo, esto eliminará el objeto al que apunta el puntero cuando es la última referencia al objeto. Este comportamiento, sin embargo, es exactamente el deseado del puntero inteligente en el primer lugar.

Si lo que desea es una referencia que no posea el objeto vivo, se puede crear un boost::weak_ptr (ver impulso documentación ). Un weak_ptr contiene una referencia al objeto pero no se suma a la cuenta de referencia, por lo que el objeto se elimina cuando sólo existen referencias débiles.

La base de compartir es la confianza. Si algún caso en su programa necesita para liberar el puntero en bruto, es casi seguro que shared_ptr es el tipo incorrecto.

Sin embargo, hace poco que quería hacer esto también, ya que tenía que cancelar la asignación de un proceso en heap diferente. Al final me enseñaron que mi decisión más para poder utilizar algunas std::shared_ptr no estaba pensada.

He utilizado solo rutinariamente este tipo de limpieza. Sin embargo, el puntero se duplica en solo unos pocos lugares. En realidad necesitaba un std::unique_ptr, que (sorpresa) tiene una función release.

Perdónalos porque no saben lo que hacen. En este ejemplo se trabaja con impulso :: shared_ptr y MSVS std :: shared_ptr sin pérdidas de memoria!

template <template <typename> class TSharedPtr, typename Type>
Type * release_shared(TSharedPtr<Type> & ptr)
{
    //! this struct mimics the data of std:shared_ptr ( or boost::shared_ptr )
    struct SharedVoidPtr
    {
        struct RefCounter
        {
            long _Uses;
            long _Weaks;
        };

        void * ptr;
        RefCounter * refC;

        SharedVoidPtr()
        {
            ptr = refC = nullptr;
        }

        ~SharedVoidPtr()
        {
            delete refC;
        }
    };

    assert( ptr.unique() );

    Type * t = ptr.get();

    SharedVoidPtr sp; // create dummy shared_ptr
    TSharedPtr<Type> * spPtr = (TSharedPtr<Type>*)( &sp );
    spPtr->swap(ptr); // swap the contents

    ptr.reset();
    // now the xxx::shared_ptr is empy and
    // SharedVoidPtr releases the raw poiter but deletes the underlying counter data
    return t;
}

Puede eliminar el puntero compartido, que parece muy similar a mí. Si punteros son siempre únicos, entonces std::auto_ptr<> es una buena opción. Tenga en cuenta que los punteros únicas que no se pueden utilizar en contenedores STL, ya que las operaciones en ellos hacen un montón de copia y duplicación temporal.

No estoy del todo seguro de si su pregunta es acerca de lograr esto, pero si quieres el comportamiento de un shared_ptr, donde, si se suelta el valor de un shared_ptr, todos los otros punteros compartidos en el mismo valor se convierten en un nullptr, a continuación, se puede poner un unique_ptr en un shared_ptr para lograr que el comportamiento.

void print(std::string name, std::shared_ptr<std::unique_ptr<int>>& ptr)
{
    if(ptr == nullptr || *ptr == nullptr)
    {
        std::cout << name << " points to nullptr" << std::endl;
    }
    else
    {
        std::cout << name << " points to value " << *(*ptr) << std::endl;
    }
}

int main()
{
    std::shared_ptr<std::unique_ptr<int>> original;
    original = std::make_shared<std::unique_ptr<int>>(std::make_unique<int>(50));

    std::shared_ptr<std::unique_ptr<int>> shared_original = original;

    std::shared_ptr<std::unique_ptr<int>> thief = nullptr;

    print(std::string("original"), original);
    print(std::string("shared_original"), shared_original);
    print(std::string("thief"), thief);

    thief = std::make_shared<std::unique_ptr<int>>(original->release());

    print(std::string("original"), original);
    print(std::string("shared_original"), shared_original);
    print(std::string("thief"), thief);

    return 0;
}

Salida:

original points to value 50
shared_original points to value 50
thief points to nullptr
original points to nullptr
shared_original points to nullptr
thief points to value 50

Este comportamiento le permite compartir un recurso (como una matriz), a continuación, volver a utilizar más adelante ese recurso, mientras que invalida todas las referencias a este recurso compartido.

Aquí hay un truco que podría funcionar. Yo no recomendaría a menos que estés en un verdadero aprieto.

template<typename T>
T * release_shared(std::shared_ptr<T> & shared)
{
    static std::vector<std::shared_ptr<T> > graveyard;
    graveyard.push_back(shared);
    shared.reset();
    return graveyard.back().get();
}

Si los punteros de verdad únicos no utilizar std::unique_ptr o boost::scoped_ptr si el primero no está disponible para su compilador. De lo contrario, considerar la combinación del uso de boost::shared_ptr con boost::weak_ptr. Echa un vistazo a la Boost documentación para más detalles.

Estoy utilizando Poco :: HTTPRequestHandlerFactory la que espera volver a HTTPRequestHandler * prima, el marco Poco elimina el controlador una vez que la solicitud termina.

También usando proyecto DI salsa para crear los controladores, sin embargo, el inyector vuelve shared_ptr que no puedo volver directamente, y devolver handler.get () no es bueno, ya sea desde la tan pronto como esta función devuelve el shared_ptr sale del ámbito y borra a continuación, antes de su handler ejecutados, por lo que aquí hay una razonable (creo) razones para tener un método .release (). Terminé la creación de una clase HTTPRequestHandlerWrapper de la siguiente manera: -

class HTTPRequestHandlerWrapper : public HTTPRequestHandler {
private:
    sauce::shared_ptr<HTTPRequestHandler> _handler;

public:
    HTTPRequestHandlerWrapper(sauce::shared_ptr<HTTPRequestHandler> handler) {
        _handler = handler;
    }

    virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
        return _handler->handleRequest(request, response);
    }
};

y luego la fábrica haría

HTTPRequestHandler* HttpHandlerFactory::createRequestHandler(const HTTPServerRequest& request) {
    URI uri = URI(request.getURI());
    auto path = uri.getPath();
    auto method = request.getMethod();

    sauce::shared_ptr<HTTPRequestHandler> handler = _injector->get<HTTPRequestHandler>(method + ":" + path);

    return new HTTPRequestHandlerWrapper(handler);
}

que satisfizo tanto la salsa y de Poco y funciona muy bien.

que tenía que pasar un puntero a través de manipuladores asincrónicos y para mantener el comportamiento auto-destrucción en caso de fallo, pero la API final se espera un puntero prima, así que hice esta función para liberar de una sola shared_ptr:

#include <memory>

template<typename T>
T * release(std::shared_ptr<T> & ptr)
{
    struct { void operator()(T *) {} } NoDelete;

    T * t = nullptr;
    if (ptr.use_count() == 1)
    {
        t = ptr.get();
        ptr.template reset<T>(nullptr, NoDelete);
    }
    return t;
}

Si ptr.use_count() != 1 se deberá obtener un nullptr lugar.

solución fácil, aumenta la referencia y después de fugas El shared_pointer.

boost::shared_ptr<MyType> shared_pointer_to_instance(new MyType());
new boost::shared_ptr<MyType>();
MyType * raw_pointer = shared_pointer_to_instance.get()

Esta claro que provocará una pérdida de memoria tanto del shared_ptr y la MyType *

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