Condividi tramite


Puntatori intelligenti (C++ moderno)

In programmazione in C++ moderno, include la libreria Standard di puntatori intelligenti, che vengono utilizzate per garantire che i programmi sono liberi di memoria e risorse delle perdite e sono indipendenti dai eccezione.

Viene utilizzato per puntatori intelligenti

I puntatori intelligenti sono definiti nel std spazio dei nomi nel <memory> file di intestazione.Essi sono di importanza fondamentale per la RAII o Initialialization È acquisizione di risorsa linguaggio di programmazione.L'obiettivo principale di questo linguaggio è garantire che l'acquisizione di risorsa si verifica contemporaneamente l'oggetto viene inizializzato in modo che tutte le risorse per l'oggetto vengono create e pronte in una riga di codice.In pratica, il principio principale di RAII consiste nell'assegnare la proprietà di qualsiasi risorsa allocati sull'heap, ad esempio memoria allocata dinamicamente o gli handle di oggetto di sistema, ovvero a un oggetto allocato nello stack cui distruttore è indicato il codice per eliminare o liberare la risorsa e per qualsiasi associato il codice di pulitura.

Nella maggior parte dei casi, quando si inizializza un handle non elaborato di puntatore o risorse per fare riferimento a risorse effettive, passare il puntatore a un puntatore intelligente immediatamente.In C++ moderno, i puntatori non elaborati vengono utilizzati solo in blocchi di codice di limitate funzioni ambito, loop o supporto in cui le prestazioni sono critiche e non vi è alcuna possibilità di confusione sulle proprietà.

Nell'esempio riportato di seguito confronta una dichiarazione di puntatore raw a una dichiarazione di puntatore intelligente.

void UseRawPointer()
{
    // Using a raw pointer -- not recommended.
    Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); 

    // Use pSong...

    // Don't forget to delete!
    delete pSong;   
}


void UseSmartPointer()
{
    // Declare a smart pointer on stack and pass it the raw pointer.
    unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

    // Use song2...
    wstring s = song2->duration_;
    //...

} // song2 is deleted automatically here.

Come illustrato nell'esempio, un puntatore intelligente è un template di classe che dichiara nello stack e inizializzare un puntatore raw che punta a un oggetto allocati sull'heap.Dopo l'inizializzazione di puntatore intelligente, è proprietario il puntatore non elaborato.Ciò significa che il puntatore intelligente è responsabile dell'eliminazione della memoria che specifica il puntatore non elaborato.Il distruttore del puntatore intelligente contiene la chiamata a eliminare e poiché il puntatore intelligente viene dichiarato nello stack, il distruttore viene richiamato quando il puntatore intelligente esce dall'ambito, anche se viene generata un'eccezione in una posizione ulteriormente lo stack.

Accedere al puntatore incapsulato utilizzando gli operatori di puntatore familiare, -> e *, che esegue l'overload della classe puntatore intelligente per restituire il puntatore raw incapsulato.

Il linguaggio del puntatore intelligente di C++ è simile a creazione di un oggetto in linguaggi quali c#: creare l'oggetto e lasciare che il sistema si occupano di l'eliminazione al momento corretto.La differenza è che nessun separato garbage collector viene eseguito in background. memoria viene gestita tramite le regole di ambito in modo che l'ambiente di runtime è più veloce ed efficiente standard di C++.

Nota importanteImportante

Creare sempre puntatori intelligenti in una riga separata del codice, mai in un elenco di parametri, in modo che non si verifica una perdita di risorse a causa di alcune regole di allocazione elenco di parametri.

Nell'esempio riportato di seguito viene illustrato come un unique_ptr tipo di puntatore intelligente dalla libreria di modelli Standard può essere utilizzato per incapsulare un puntatore a un oggetto di grandi dimensioni.


class LargeObject
{
public:
    void DoSomething(){}
};

void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{    
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass a reference to a method.
    ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope.

L'esempio dimostra i seguenti passaggi fondamentali per l'utilizzo di puntatori intelligenti.

  1. Dichiarare il puntatore intelligente come una variabile automatica (locale).(Non utilizzare il new o malloc espressione sul puntatore intelligente a se stesso.)

  2. Nel parametro di tipo, specificare il tipo a cui punta del puntatore incapsulato.

  3. Passare un puntatore raw a un new-oggetto ed il costruttore di un puntatore intelligente.(Alcune funzioni di utilità o costruttori di puntatore intelligente farlo per voi.)

  4. Utilizzare il metodo di overload -> e * operatori per accedere all'oggetto.

  5. Il puntatore intelligente è possibile eliminare l'oggetto.

I puntatori intelligenti sono progettati per essere efficace come possibili in termini di prestazioni e memoria.Ad esempio, il membro dati solo in unique_ptr è il puntatore incapsulato.Ciò significa che unique_ptr è esattamente le stesse dimensioni di tale puntatore, byte quattro o otto byte.L'accesso al puntatore incapsulato utilizzando il puntatore intelligente di overload * e - > gli operatori non è molto più lento rispetto all'accesso i puntatori non elaborati direttamente.

I puntatori intelligenti sono le proprie funzioni membro, in cui sono possibile accedere tramite la notazione "dot".Ad esempio, alcuni puntatori intelligenti STL hanno una funzione membro di reimpostazione rilascia proprietario del puntatore.Ciò è utile quando si desidera liberare la memoria di proprietà puntatore intelligente prima che il puntatore intelligente esce dall'ambito, come illustrato nell'esempio riportato di seguito.

void SmartPointerDemo2()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Free the memory before we exit function block.
    pLarge.reset();

    // Do some other work...

}

In genere, i puntatori intelligenti forniscono un modo per accedere direttamente ai loro puntatore raw.Puntatori intelligenti STL sono un get funzione membro a tal fine, e CComPtr dispone di un pubblico p membro della classe.Grazie all'accesso diretto al puntatore sottostante, è possibile utilizzare il puntatore intelligente per la gestione della memoria nel proprio codice e comunque passare il puntatore raw al codice che non supportano i puntatori intelligenti.

void SmartPointerDemo4()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass raw pointer to a legacy API
    LegacyLargeObjectFunction(pLarge.get());    
}

Tipi di puntatori intelligenti

Nella sezione seguente sono riepilogati i diversi tipi di puntatori intelligenti sono disponibili nell'ambiente di programmazione di Windows e viene descritto quando utilizzarle.

  • Puntatori intelligenti di libreria Standard di C++
    Utilizzare questi puntatori intelligenti di prima scelta per l'incapsulamento di puntatori a oggetti C++ vecchi normali (POCO).

    • unique_ptr
      Consente un solo proprietario del puntatore sottostante.Utilizzare come scelta predefinita per POCO, a meno che non si è certi che richiedono un shared_ptr.Può essere spostato in un nuovo proprietario, ma non copiati o condivisi.Sostituisce auto_ptr, che è obsoleto.Confrontare con boost::scoped_ptr.unique_ptrè piccola ed efficiente; la dimensione è un puntatore e supporta i riferimenti di rvalue per inserimento rapido e il recupero di insiemi STL.File di intestazione: <memory>.Per ulteriori informazioni, vedere Procedura: Creare e utilizzare le istanze di unique_ptr e unique_ptr Class.

    • shared_ptr
      Puntatore intelligente conteggio dei riferimenti.Utilizzare questo campo assegnare un puntatore raw a più proprietari, ad esempio, quando si restituisce una copia di un puntatore da un contenitore ma si desidera conservare l'originale.Puntatore raw non viene eliminato finché tutte le shared_ptr proprietari sono esterne all'ambito o in caso contrario hanno dato proprietario.La dimensione è di due puntatori. uno per l'oggetto e uno per il blocco di controllo condiviso che contiene il conteggio dei riferimenti.File di intestazione: <memory>.Per ulteriori informazioni, vedere Procedura: Creare e utilizzare le istanze di shared_ptr e shared_ptr Class.

    • weak_ptr
      Puntatore intelligente speciale da utilizzare in combinazione con shared_ptr.A weak_ptr fornisce l'accesso a un oggetto che appartiene a uno o più shared_ptr le istanze, ma non fa parte di conteggio dei riferimenti.Utilizzare quando si desidera osservare un oggetto, ma non è necessario rimanere attivo.Necessaria in alcuni casi per interrompere i riferimenti circolari tra shared_ptr le istanze.File di intestazione: <memory>.Per ulteriori informazioni, vedere Procedura: Creare e utilizzare le istanze di weak_ptr e weak_ptr Class.

  • Puntatori intelligenti per gli oggetti COM (programmazione Windows classica)
    Quando si lavora con gli oggetti COM, racchiudere i puntatori di interfaccia in un tipo puntatore intelligente appropriato.La libreria ATL (Active Template) definisce numerosi puntatori intelligenti per vari scopi.È inoltre possibile utilizzare il _com_ptr_t tipo di puntatore intelligente, il compilatore utilizza durante la creazione di classi wrapper dal file con estensione tlb.È la scelta migliore quando non si desidera includere i file di intestazione ATL.

  • Puntatori intelligenti ATL per gli oggetti POCO
    Oltre a puntatori intelligenti per gli oggetti COM, ATL definisce inoltre i puntatori intelligenti e insiemi di puntatori intelligenti per la normali vecchi oggetti C++.Nella programmazione Windows classico, questi tipi sono un'utile alternativa agli insiemi STL, soprattutto quando non è necessaria la portabilità del codice o quando non si desidera combinare i modelli di programmazione di STL e ATL.

    • Classe CAutoPtr
      Puntatore intelligente che impone di proprietà univoco per il trasferimento della proprietà nella copia.Comparabili per l'obsoleto std::auto_ptr classe.

    • Classe CHeapPtr
      Puntatore intelligente per gli oggetti che vengono allocati utilizzando c malloc funzione.

    • Classe CAutoVectorPtr
      Puntatore intelligente per le matrici vengono allocati tramite new[].

    • Classe CAutoPtrArray
      Classe che incapsula una matrice di CAutoPtr gli elementi.

    • Classe CAutoPtrList
      Classe che incapsula i metodi per la modifica di un elenco di CAutoPtr i nodi.

Vedere anche

Altre risorse

Digitare di nuovo a C++ (C++ moderno)

Riferimenti al linguaggio C++

Riferimento della libreria C++ standard

Cenni preliminari su: Gestione della memoria in C++