Domanda

Ho riflettuto sull'uso di unique_ptr contro shared_ptr contro own_solution.Ho scartato quest'ultimo perché quasi sicuramente sbaglierò, ma ho un problema con entrambi unique_ptr E shared_ptr in quanto nessuno dei due cattura esattamente ciò che voglio.Desidero creare un gestore delle risorse che possiede esplicitamente una risorsa, tuttavia vorrei che il gestore delle risorse distribuisse anche i riferimenti alla risorsa.

Se uso unique_ptr nel gestore delle risorse e distribuire puntatori grezzi c'è la possibilità che possano scappare altrove (anche se suppongo questo sarebbe contro il "contratto" della classe).Se uso shared_ptr e distribuire weak_ptr, non c'è nulla che impedisca a un chiamante di convertire il file weak_ptr ad a shared_ptr e immagazzinarlo, creando così potenzialmente un ciclo o, peggio, una risorsa che vive oltre la vita del gestore delle risorse.Quindi suppongo che quello che sto cercando sia un differibile weak_ptr che non può essere convertito in a shared_ptr.

O sto solo cercando di far rispettare il contratto con alcuni commenti fortemente formulati nel codice?

Grazie per qualsiasi pensiero tu possa avere a riguardo.

È stato utile?

Soluzione

I puntatori intelligenti come shared_ptr e unique_ptr sono un buon attrezzo quando hai possedere puntatori.
Ma per i puntatori non proprietari, I.e. osservando i puntatori , usando un puntatore grezzo è solo bene.

Nel tuo design, penso che il gestore delle risorse sia l'unico "proprietario" delle risorse, in modo da poter semplicemente avere qualche forma di puntatore intelligente interno il gestore delle risorse.Ad esempio, il gestore delle risorse può avere un std::vector<std::unique_ptr<Resource>> come membro dei dati, o anche un std::vector<Resource> più semplice se la classe Resource è progettata per essere eseguita correttamente in un std::vector.

Quindi, il gestore delle risorse può dare ai puntatori di osservazione non proprietari non proprietari e puntatori grezzi (o riferimenti C ++) vanno bene per questo caso.

Certo, è importante che la durata del gestore delle risorse superi quella dei "client di risorse".

Altri suggerimenti

Alla fine, non puoi costringere nessuno ad ascoltare.Chiedi a Microsoft, Apple o qualsiasi sviluppatore di librerie open source, conoscono tutti quella canzone.Un commento con le parole e i posti giusti è la soluzione migliore.

Evita di creare la tua classe puntatore intelligente, ostacola la composizione e riduce la leggibilità.Come ultima risorsa, prova a cercare in boost o in qualsiasi framework con cui il tuo codice deve già funzionare.

Se ci sono non proprietari, sono eleggibili per la detenzione weak_ptrs o (se è garantito che rimanga valido per tutta la durata) puntatori grezzi.
Se usi shared_ptrs internamente (perché dovresti), è meglio fornire weak_ptr e puntatori grezzi.

Tutti questi puntatori intelligenti denotano esplicitamente una politica di proprietà.I puntatori grezzi denotano nessuno o non proprietario.

  • auto_ptr:Da non usare, deprecato con troppe trappole anche per i diffidenti.
  • unique_ptr:Proprietà unica.
  • shared_ptr:Proprietà condivisa
  • weak_ptr:Nessuna proprietà, potresti essere cancellato alle tue spalle.
  • puntatore grezzo
    • Esplicitamente nessuna proprietà con durata garantita maggiore
    • o gestione manuale della proprietà.
.

Quindi suppongo quello che sto cercando è un deferente deble_ptr che non può essere convertito in uno shared_ptr.

Puoi distribuire la tua piccola classe di helper:

template<typename T>
class NonConvertibleWeakPtr
{
public:
   NonConvertibleWeakPtr(const std::shared_ptr<T>& p) : p_(p) {}
   ... // other constructors / assignment operators
   bool expired() const { return p_.expired(); }
   T* operator->() const { return get(); }
   T& operator*() const { return *get(); }
private:
   T* get() const { return p_.lock().get(); }
private:
   std::weak_ptr<T> p_;
};
.

Questo è leggermente migliore di un puntatore grezzo, perché puoi controllare se il puntatore è ancora valido.

Esempio di utilizzo:

std::shared_ptr<int> sp = std::make_shared<int>(5);
{
    NonConvertibleWeakPtr<int> wp(sp);
    if(!wp.expired()) {
        std::cout << *wp << std::endl;
    }
}
.

Comunque un utente può ancora usarlo abusare ad esempio con std::shared_ptr<T> blah(&(*wp));, ma ci vuole un po 'più energia criminale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top