40 votes

Comment libérer le pointeur de boost :: shared_ptr?

Est-ce que boost :: shared_ptr peut libérer le pointeur stocké sans le supprimer?

Je peux voir qu'aucune fonction de libération n'existe dans la documentation, également dans la FAQ est expliqué pourquoi il ne fournit pas de fonction de libération, quelque chose comme ça, la libération ne peut pas être effectuée sur des pointeurs qui ne sont pas uniques. Mes pointeurs sont uniques. Comment puis-je libérer mes pointeurs? Ou quelle classe de pointeur intelligent utiliser pour me permettre de libérer le pointeur? J'espère que vous ne direz pas utiliser auto_ptr :)

31voto

sellibitze Points 13607

Ne le faites pas. Stimuler l'entrée de la FAQ:

Q. Pourquoi ne pas shared_ptr fournir une fonction release ()?

Un. shared_ptr ne peuvent pas donner de propriété à moins qu'il est unique() parce que l'autre copie sera encore détruire l'objet.

Considérer:

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.

En outre, le pointeur retourné par release() serait difficile à libérer de manière fiable, en tant que source shared_ptr pourrait avoir été créé avec une coutume deleter.

Donc, ce serait en sécurité dans le cas où c'est la seule shared_ptr instance pointant vers votre objet (quand unique() retourne true (vrai) et que l'objet n'a pas besoin d'un deleter. J'avais toujours la question de votre conception, si vous avez utilisé un tel .release() fonction.

24voto

Kirill V. Lyadvinsky Points 47627

Vous pouvez utiliser un faux deleter. Les pointeurs ne seront alors pas supprimés.

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

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

7voto

curiousguy Points 2900

Les enfants, ne faites pas cela à la maison:

// 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;
}

Maintenant, est-il un moyen de vérifier si le nombre total de propriétaires pour la ref nombre est > 1?

4voto

Timbo Points 14117

Pour laisser le pointeur pointer sur rien de nouveau, vous pouvez appeler shared_ptr::reset().

Toutefois, cette opération va supprimer l'objet pointé lorsque le pointeur de la souris est la dernière référence à l'objet. Ceci, cependant, est exactement le comportement souhaité de la smart pointeur dans la première place.

Si vous voulez juste une référence qui ne tient pas l'objet vivant, vous pouvez créer un boost::weak_ptr (voir le boost de la documentation). Un weak_ptr contient une référence à l'objet, mais ne pas ajouter à la valeur de référence, l'objet est supprimé quand seulement la faiblesse des références existent.

2voto

Alexander Drichel Points 129

Pardonne-leur car ils ne savent ce qu'ils font. Cet exemple fonctionne avec boost::shared_ptr et msvs std::shared_ptr sans fuites de mémoire!

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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X