Che cos'è un puntatore intelligente e quando dovrei usarne uno?


1821

Che cos'è un puntatore intelligente e quando dovrei usarne uno?


7
Dai un'occhiata a questa domanda: <br> Smart Pointers: O chi ti possiede bambino
Martin York,

2
Si noti che l'implementazione di std :: auto_ptr in Visual Studio 2005 è terribilmente interrotta. <br> http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871 <br> http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842 Usa il aumentare quelli invece.
Richard,

25
Due articoli eccellenti sull'argomento: - Puntatori intelligenti - Cosa, perché, quale? - Guru of the Week # 25
Lazer,

1
Ecco il capitolo (gratuito) di Alexandrescu sull'ottimo spirito di creare puntatori intelligenti di diversi gusti: informit.com/articles/article.aspx?p=31529 Nella sua implementazione, usa gli argomenti del modello come "politiche" per specificare quali attributi desidera ( ad es. conteggio dei riferimenti), mentre la libreria standard utilizza classi separate. Nota che stava anche scrivendo prima che fossero disponibili riferimenti a rvalue per rendere possibile qualcosa come std :: unique_ptr.
metallo

Vorrei aggiungere un altro punto alla domanda precedente, il puntatore intelligente std :: shared_ptr non ha un operatore di sottoscrizione e non supporta l'aritmetica ponter, possiamo usare get () per ottenere un puntatore incorporato.
Suresh,

Risposte:


1884

AGGIORNARE

Questa risposta è piuttosto vecchia e descrive quindi ciò che era "buono" al momento, che era un puntatore intelligente fornito dalla libreria Boost. Dal momento che C ++ 11, la libreria standard ha fornito sufficienti tipi puntatori intelligenti, e così si dovrebbe favorire l'uso di std::unique_ptr, std::shared_ptre std::weak_ptr.

C'era anche std::auto_ptr. Era molto simile a un puntatore con ambito, tranne per il fatto che aveva anche la "speciale" pericolosa capacità di essere copiata, che trasferiva inaspettatamente la proprietà.
È stato deprecato in C ++ 11 e rimosso in C ++ 17 , quindi non dovresti usarlo.

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

VECCHIA RISPOSTA

Un puntatore intelligente è una classe che avvolge un puntatore C ++ 'grezzo' (o 'nudo'), per gestire la durata dell'oggetto a cui si punta. Non esiste un singolo tipo di puntatore intelligente, ma tutti cercano di astrarre un puntatore non elaborato in modo pratico.

I puntatori intelligenti dovrebbero essere preferiti ai puntatori non elaborati. Se ritieni di dover usare i puntatori (prima considera se lo fai davvero ), normalmente vorresti usare un puntatore intelligente poiché questo può alleviare molti dei problemi con i puntatori non elaborati, dimenticandoti principalmente di eliminare l'oggetto e perdere memoria.

Con puntatori non elaborati, il programmatore deve distruggere esplicitamente l'oggetto quando non è più utile.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

Un puntatore intelligente al confronto definisce una politica su quando l'oggetto viene distrutto. Devi ancora creare l'oggetto, ma non devi più preoccuparti di distruggerlo.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

La politica più semplice in uso riguarda l'ambito dell'oggetto wrapper puntatore intelligente, come implementato da boost::scoped_ptro std::unique_ptr.

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Si noti che le std::unique_ptristanze non possono essere copiate. Ciò impedisce che il puntatore venga eliminato più volte (in modo errato). Tuttavia, è possibile passare riferimenti ad esso ad altre funzioni chiamate.

std::unique_ptrsono utili quando si desidera associare la durata dell'oggetto a un determinato blocco di codice o se lo si è incorporato come dati membro all'interno di un altro oggetto, la durata di quell'altro oggetto. L'oggetto esiste fino all'uscita dal blocco di codice contenente o fino a quando l'oggetto contenitore non viene distrutto.

Una politica di puntatore intelligente più complessa prevede il conteggio dei riferimenti del puntatore. Ciò consente di copiare il puntatore. Quando l'ultimo "riferimento" all'oggetto viene distrutto, l'oggetto viene eliminato. Questa politica è implementata da boost::shared_ptre std::shared_ptr.

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

I puntatori contati di riferimento sono molto utili quando la durata del tuo oggetto è molto più complicata e non è legata direttamente a una particolare sezione di codice o ad un altro oggetto.

C'è un inconveniente per fare riferimento ai puntatori contati: la possibilità di creare un riferimento pendente:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Un'altra possibilità è la creazione di riferimenti circolari:

struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

Per aggirare questo problema, sia Boost che C ++ 11 hanno definito a weak_ptrper definire un riferimento debole (non contato) a a shared_ptr.


7
Intendi std::auto_ptr<MyObject> p1 (new MyObject());invece std::auto_ptr<MyObject> p1 (new Owner());?
Mateen Ulhaq,

35
Risposta fantastica. Sarebbe bello se fosse aggiornato per c ++ 11. Ho trovato questa risposta cercando informazioni sul nuovo standard 11 e sarebbe bello se i futuri visitatori potessero trovare le informazioni aggiornate. So che auto_ptr è stato deprecato. Credo che shated_ptr e weak_ptr esistano come descritto e penso che scoped_ptr sia ora unique_ptr nello standard. Se questo è vero, questa risposta può essere aggiornata per favore?
SaulBack,

16
Dire che la possibilità di creare un riferimento pendente è uno svantaggio del riferimento ai puntatori conteggiati è assolutamente folle. I possibili riferimenti pendenti sono uno svantaggio di qualsiasi puntatore C ++ . In effetti, è esattamente questo inconveniente che i puntatori intelligenti intendono alleviare .
Michael Dorst,

16
Se si dichiara un puntatore a un puntatore intelligente (come è stato fatto nell'esempio) si rinuncia consapevolmente a tutti i vantaggi del puntatore intelligente. Questo non è uno svantaggio o un difetto di progettazione, è l'uso più idiota che si possa immaginare.
Michael Dorst,

3
A const std::auto_ptrè sicuro da usare, se sei bloccato con C ++ 03. L'ho usato abbastanza per il modello pimpl fino a quando non ho avuto accesso a C ++ 11.
Toby Speight,

303

Ecco una semplice risposta per questi giorni del moderno C ++ (C ++ 11 e versioni successive):

  • Che cos'è un puntatore intelligente?
    È un tipo i cui valori possono essere usati come puntatori, ma che fornisce la funzionalità aggiuntiva della gestione automatica della memoria: quando un puntatore intelligente non è più in uso, la memoria a cui punta viene deallocata (vedere anche la definizione più dettagliata su Wikipedia ).
  • Quando dovrei usarne uno?
    Nel codice che prevede il monitoraggio della proprietà di un pezzo di memoria, l'allocazione o la disallocazione; il puntatore intelligente spesso ti fa risparmiare la necessità di fare esplicitamente queste cose.
  • Ma quale puntatore intelligente dovrei usare in quale di questi casi?
    • Utilizzare std::unique_ptrquando non si intende contenere più riferimenti allo stesso oggetto. Ad esempio, utilizzarlo per un puntatore alla memoria che viene allocato all'ingresso di un ambito e disallocato all'uscita dall'ambito.
    • Utilizzare std::shared_ptrquando si desidera fare riferimento al proprio oggetto da più punti - e non si desidera che il proprio oggetto venga disallocato fino a quando tutti questi riferimenti non saranno scomparsi.
    • Utilizzare std::weak_ptrquando si desidera fare riferimento al proprio oggetto da più punti, per quei riferimenti per i quali è ok ignorare e deallocare (quindi noteranno solo che l'oggetto è sparito quando si tenta di dereferenziare).
    • Non utilizzare i boost::puntatori intelligenti o std::auto_ptrtranne in casi speciali sui quali è possibile leggere se è necessario.
  • Ehi, non ho chiesto quale usare!
    Ah, ma lo volevi davvero, ammettilo.
  • Quindi, quando dovrei usare puntatori regolari allora?
    Principalmente nel codice che è ignaro della proprietà della memoria. Ciò si verifica generalmente in funzioni che ottengono un puntatore da qualche altra parte e non allocano né disallocano e non memorizzano una copia del puntatore che sopravvive alla loro esecuzione.

5
Vale la pena notare che mentre i puntatori intelligenti (proprietari) aiutano con una corretta gestione della memoria, i puntatori grezzi (non proprietari) sono ancora utili per altri scopi organizzativi nelle strutture di dati. Herb Sutter ha fatto un'ottima presentazione su questo argomento al CppCon 2016, che puoi vedere su YouTube: Leak-Freedom in C ++ ... Per impostazione predefinita.
wiktor.wandachowicz,

1
@ wiktor.wandachowicz T*è quello std::unique_ptr<T>che std::weak_ptr<T>deve farestd::shared_ptr<T>
Caleth,

@Caleth: No, non lo direi.
einpoklum,

1
@TonyTannous: Con rispetto - È stata una modifica importante; e non sento la mia risposta, che è astratta, ne ha bisogno. Ti suggerisco di rendere l'esempio una risposta separata, sul link ad esso in un commento.
einpoklum,

112

Il puntatore intelligente è un tipo di puntatore con alcune funzionalità aggiuntive, ad esempio deallocazione automatica della memoria, conteggio dei riferimenti, ecc.

Piccola introduzione è disponibile a pagina Puntatori intelligenti: cosa, perché, quale? .

Uno del tipo di puntatore intelligente semplice è std::auto_ptr(capitolo 20.4.5 dello standard C ++), che consente di deallocare automaticamente la memoria quando non rientra nell'ambito e che è più robusto del semplice utilizzo del puntatore quando vengono generate eccezioni, sebbene meno flessibile.

Un altro tipo conveniente è quello boost::shared_ptrche implementa il conteggio dei riferimenti e disloca automaticamente la memoria quando non rimane alcun riferimento all'oggetto. Questo aiuta a evitare perdite di memoria ed è facile da usare per implementare RAII .

L'argomento è approfondito nel libro "Modelli C ++: la guida completa" di David Vandevoorde, Nicolai M. Josuttis , capitolo 20. Puntatori intelligenti. Alcuni argomenti trattati:


2
L'avvertimento std::auto_ptrè deprecato e altamente scoraggiante in quanto è possibile trasferire accidentalmente la proprietà. - C ++ 11 elimina la necessità di Boost, uso: std::unique_ptr, std::shared_ptrestd::weak_ptr
ninMonkey

42

Le definizioni fornite da Chris, Sergdev e Llyod sono corrette. Preferisco una definizione più semplice, però, solo per semplificarmi la vita: un puntatore intelligente è semplicemente una classe che sovraccarica gli operatori -> e *. Il che significa che il tuo oggetto sembra semanticamente un puntatore ma puoi farlo fare cose più interessanti, tra cui il conteggio dei riferimenti, la distruzione automatica ecc. shared_ptrE auto_ptrsono sufficienti nella maggior parte dei casi, ma arrivano con il loro set di piccole idiosincrasie.


30

Un puntatore intelligente è come un normale puntatore (tipizzato), come "char *", tranne quando il puntatore stesso esce dal campo di applicazione e quindi viene eliminato anche ciò a cui punta. Puoi usarlo come faresti con un normale puntatore, usando "->", ma non se hai bisogno di un vero puntatore ai dati. Per questo, puoi usare "& * ptr".

È utile per:

  • Oggetti che devono essere allocati con nuovi, ma che vorresti avere la stessa durata di qualcosa nello stack. Se l'oggetto viene assegnato a un puntatore intelligente, verranno eliminati quando il programma esce da quella funzione / blocco.

  • Membri dei dati delle classi, in modo che quando l'oggetto viene eliminato anche tutti i dati di proprietà vengano eliminati, senza alcun codice speciale nel distruttore (sarà necessario assicurarsi che il distruttore sia virtuale, il che è quasi sempre una buona cosa da fare) .

Potresti non voler utilizzare un puntatore intelligente quando:

  • ... il puntatore non dovrebbe in realtà possedere i dati ... vale a dire, quando si stanno semplicemente usando i dati, ma si desidera che sopravvivano alla funzione in cui si fa riferimento.
  • ... il puntatore intelligente non verrà distrutto a un certo punto. Non vuoi che rimanga nella memoria che non viene mai distrutta (come in un oggetto allocato dinamicamente ma che non verrà eliminato esplicitamente).
  • ... due puntatori intelligenti potrebbero puntare agli stessi dati. (Ci sono, tuttavia, puntatori ancora più intelligenti che gestiranno quello ... che si chiama conteggio dei riferimenti .)

Guarda anche:


18

La maggior parte dei tipi di puntatori intelligenti gestiscono l'eliminazione dell'oggetto puntatore a voi. È molto utile perché non devi più pensare a smaltire gli oggetti manualmente.

I puntatori intelligenti più comunemente usati sono std::tr1::shared_ptr(o boost::shared_ptr), e, meno comunemente, std::auto_ptr. Raccomando l'uso regolare di shared_ptr.

shared_ptrè molto versatile e si occupa di una grande varietà di scenari di smaltimento, inclusi i casi in cui gli oggetti devono essere "passati attraverso i confini della DLL" (il caso dell'incubo comune se libcsi usano s diversi tra il codice e le DLL).


18

Un puntatore intelligente è un oggetto che agisce come un puntatore, ma fornisce inoltre controllo su costruzione, distruzione, copia, spostamento e dereferenziazione.

È possibile implementare il proprio puntatore intelligente, ma molte librerie forniscono anche implementazioni di puntatori intelligenti, ognuna con vantaggi e svantaggi diversi.

Ad esempio, Boost fornisce le seguenti implementazioni di puntatori intelligenti:

  • shared_ptr<T>è un puntatore Tall'utilizzo di un conteggio di riferimento per determinare quando l'oggetto non è più necessario.
  • scoped_ptr<T>è un puntatore eliminato automaticamente quando esce dall'ambito. Nessun incarico è possibile.
  • intrusive_ptr<T>è un altro puntatore di conteggio dei riferimenti. Offre prestazioni migliori rispetto a shared_ptr, ma richiede al tipo Tdi fornire il proprio meccanismo di conteggio dei riferimenti.
  • weak_ptr<T>è un puntatore debole, che lavora insieme shared_ptrper evitare riferimenti circolari.
  • shared_array<T>è come shared_ptr, ma per array di T.
  • scoped_array<T>è come scoped_ptr, ma per array di T.

Queste sono solo una descrizione lineare di ciascuna e possono essere utilizzate secondo necessità, per ulteriori dettagli ed esempi si può consultare la documentazione di Boost.

Inoltre, la libreria standard C ++ fornisce tre puntatori intelligenti; std::unique_ptrper proprietà unica, std::shared_ptrper proprietà condivisa e std::weak_ptr. std::auto_ptresisteva in C ++ 03 ma ora è deprecato.


Spiegare perché scoped_ptrnon è come un dichiarato localmente, const unique_ptrche viene eliminato anche all'uscita dall'ambito.
einpoklum,

11

Ecco il link per risposte simili: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Un puntatore intelligente è un oggetto che agisce, appare e si sente come un normale puntatore ma offre più funzionalità. In C ++, i puntatori intelligenti sono implementati come classi di modelli che incapsulano un puntatore e sovrascrivono gli operatori di puntatori standard. Hanno una serie di vantaggi rispetto ai puntatori regolari. Sono garantiti per essere inizializzati come puntatori null o puntatori a un oggetto heap. L'indirizzamento tramite un puntatore null è verificato. Nessuna cancellazione è mai necessaria. Gli oggetti vengono liberati automaticamente quando l'ultimo puntatore è scomparso. Un problema significativo con questi puntatori intelligenti è che, a differenza dei puntatori normali, non rispettano l'eredità. I puntatori intelligenti non sono attraenti per il codice polimorfico. Di seguito è riportato un esempio per l'implementazione di puntatori intelligenti.

Esempio:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

Questa classe implementa un puntatore intelligente su un oggetto di tipo X. L'oggetto stesso si trova sull'heap. Ecco come usarlo:

smart_pointer <employee> p= employee("Harris",1333);

Come altri operatori sovraccarichi, p si comporterà come un normale puntatore,

cout<<*p;
p->raise_salary(0.5);

9

http://en.wikipedia.org/wiki/Smart_pointer

In informatica, un puntatore intelligente è un tipo di dati astratto che simula un puntatore fornendo allo stesso tempo funzionalità aggiuntive, come la garbage collection automatica o il controllo dei limiti. Queste funzionalità aggiuntive hanno lo scopo di ridurre i bug causati dall'uso improprio dei puntatori mantenendo l'efficienza. I puntatori intelligenti in genere tengono traccia degli oggetti che puntano ad essi ai fini della gestione della memoria. L'uso improprio dei puntatori è una delle principali fonti di bug: l'allocazione, la deallocazione e il riferimento costanti che devono essere eseguiti da un programma scritto utilizzando i puntatori rendono molto probabile che si verifichino perdite di memoria. I puntatori intelligenti cercano di prevenire perdite di memoria rendendo automatica la deallocazione delle risorse: quando il puntatore a un oggetto (o l'ultimo di una serie di puntatori) viene distrutto,


6

Sia T una classe in questo tutorial I puntatori in C ++ possono essere divisi in 3 tipi:

1) Puntatori non elaborati :

T a;  
T * _ptr = &a; 

Conservano un indirizzo di memoria in una posizione nella memoria. Usare con cautela, poiché i programmi diventano difficili da tenere traccia.

Puntatori con dati const o indirizzo {Leggi indietro}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

Puntatore a un tipo di dati T che è una const. Ciò significa che non è possibile modificare il tipo di dati utilizzando il puntatore. cioè *ptr1 = 19; non funzionerà. Ma puoi spostare il puntatore. cioè ptr1++ , ptr1--; ecc funzionerà. Leggi all'indietro: puntatore al tipo T che è const

  T * const ptr2 ;

Un puntatore const a un tipo di dati T. Ciò significa che non è possibile spostare il puntatore ma è possibile modificare il valore indicato dal puntatore. cioè *ptr2 = 19funzionerà ma ptr2++ ; ptr2--ecc non funzionerà. Leggi indietro: puntatore const a un tipo T

const T * const ptr3 ; 

Un puntatore const a un tipo di dati const T. Ciò significa che non è possibile spostare il puntatore né modificare il puntatore del tipo di dati in modo che diventi il ​​puntatore. cioè ptr3-- ; ptr3++ ; *ptr3 = 19;non funzionerà

3) Puntatori intelligenti : { #include <memory>}

Puntatore condiviso :

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

Implementato utilizzando il conteggio dei riferimenti per tenere traccia di quante "cose" puntano all'oggetto puntato dal puntatore. Quando questo conteggio va a 0, l'oggetto viene automaticamente eliminato, ovvero l'oggetto viene eliminato quando tutto lo share_ptr che punta all'oggetto non rientra nell'ambito. Questo elimina il mal di testa di dover eliminare gli oggetti che hai allocato usando new.

Puntatore debole: aiuta a gestire il riferimento ciclico che si presenta quando si utilizza il puntatore condiviso Se si hanno due oggetti puntati da due puntatori condivisi e c'è un puntatore condiviso interno che punta a vicenda puntatore condiviso, ci sarà un riferimento ciclico e l'oggetto non essere eliminato quando i puntatori condivisi non rientrano nell'ambito. Per risolvere questo, cambia il membro interno da shared_ptr a weak_ptr. Nota: per accedere all'elemento puntato da un puntatore debole usare lock (), questo restituisce un punto debole.

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

Vedi: quando è utile std :: weak_ptr?

Puntatore unico: puntatore intelligente leggero con proprietà esclusiva. Utilizzare quando il puntatore punta a oggetti unici senza condividere gli oggetti tra i puntatori.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

Per modificare l'oggetto a cui punta il ptr univoco, utilizzare la semantica di spostamento

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

Riferimenti: possono essenzialmente essere considerati puntatori const, ovvero un puntatore che è const e non può essere spostato con una migliore sintassi.

Vedi: Quali sono le differenze tra una variabile puntatore e una variabile di riferimento in C ++?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

Riferimento: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Grazie ad Andre per aver sottolineato questa domanda.


3

Un puntatore intelligente è una classe, un wrapper di un puntatore normale. A differenza dei normali puntatori, il cerchio di vita di smart point si basa su un conteggio di riferimento (quante volte viene assegnato l'oggetto puntatore intelligente). Pertanto, ogni volta che un puntatore intelligente viene assegnato a un altro, il riferimento interno conta più più. E ogni volta che l'oggetto esce dall'ambito, il conteggio di riferimento meno meno.

Il puntatore automatico, sebbene sembri simile, è totalmente diverso dal puntatore intelligente. È una classe conveniente che dealloca la risorsa ogni volta che un oggetto puntatore automatico esce dall'ambito variabile. In una certa misura, fa funzionare un puntatore (alla memoria allocata dinamicamente) in modo simile a una variabile di stack (allocata staticamente nel tempo di compilazione).


2

I puntatori intelligenti sono quelli in cui non devi preoccuparti della disallocazione della memoria, della condivisione delle risorse e del trasferimento.

Puoi benissimo usare questi puntatori nello stesso modo in cui qualsiasi allocazione funziona in Java. In java Garbage Collector fa il trucco, mentre in Smart Pointers il trucco è fatto dai Distruttori.


1

Le risposte esistenti sono buone ma non coprono cosa fare quando un puntatore intelligente non è la risposta (completa) al problema che si sta tentando di risolvere.

Tra l'altro (spiegato bene in altre risposte) l'uso di un puntatore intelligente è una possibile soluzione a Come possiamo usare una classe astratta come tipo di ritorno di funzione? che è stato contrassegnato come duplicato di questa domanda. Tuttavia, la prima domanda da porsi se si è tentati di specificare una classe base astratta (o di fatto una qualsiasi) come tipo di ritorno in C ++ è "cosa intendi veramente?". C'è una buona discussione (con ulteriori riferimenti) sulla programmazione orientata agli oggetti idiomatica in C ++ (e come questo è diverso da altri linguaggi) nella documentazione della libreria contenitore puntatore boost. In sintesi, in C ++ devi pensare alla proprietà. Quali smart pointer ti aiutano, ma non sono l'unica soluzione, o sempre una soluzione completa (non ti danno una copia polimorfica) e non sono sempre una soluzione che vuoi esporre nella tua interfaccia (e una funzione di ritorno suona terribile molto simile a un'interfaccia). Potrebbe essere sufficiente restituire un riferimento, ad esempio. Ma in tutti questi casi (puntatore intelligente, contenitore puntatore o semplicemente restituendo un riferimento) è stato modificato il ritorno da un valore a una forma di riferimento . Se hai davvero bisogno di una copia, potresti aver bisogno di aggiungere più "idioma" o di andare oltre OO idiomatico (o altrimenti) in C ++ a polimorfismo più generico usando librerie come Adobe Poly o Boost..

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.