2010-01-20 21 views
6

Quali sono i vantaggi e gli svantaggi dell'utilizzo di puntatori automatici (auto_ptr), rispetto ai puntatori ordinari? Ho sentito che rilascia automaticamente la memoria, ma come mai non viene usato spesso?Vantaggi/svantaggi dei puntatori automatici

+3

The Law of Leaky Abstractions: http://www.joelonsoftware.com/articles/LeakyAbstractions.html –

+1

Nota: std :: auto_ptr è solo uno di un intero insieme di puntatori intelligenti utilizzati in C++. –

+1

OK. Capisco meglio la tua domanda ora. Sì std :: auto :: ptr sono i meno utilizzati, ma non dovresti guardarli da soli. Fanno parte dell'insieme di puntatori intelligenti e hanno il loro uso specifico. Un buon uso di std :: auto_ptr è la documentazione del trasferimento di proprietà. –

risposta

10

Lo svantaggio principale di std::auto_ptr è che ha il trasferimento di proprietà semantico. Ciò rende impossibile memorizzare std::auto_ptr in contenitori STL perché i contenitori utilizzano il costruttore di copie quando si memorizza o si ottiene un elemento.

Inoltre, un altro aspetto importante che ho notato sul std::auto_ptr è che non possono servire nell'uso di idioma PIMPL. Questo perché richiedono la definizione completa del distruttore della classe spostata. Vedi il thread this su c.l.C++. M per una discussione più dettagliata.

Aggiornamento: Trasferimento di proprietà

class Test {}; 
std::auto_ptr<Test> ap_test_1(new Test); 
std::auto_ptr<Test> ap_test_2(new Test); 

ap_test_2 = ap_test_1; // here ap_test_1's ownership is transferred i.e. ap_test_2 is the 
         // new owner and ap_test_1 is NULL. 

Vedere this discussione sul sito di Herb Sutter per maggiori dettagli su ciò che questo significa quando viene utilizzato in un contenitore STL utilizzato da algoritmi STL.

+0

Sì, penso che questo risponda alla mia domanda, ma puoi spiegare di più su questo trasferimento di proprietà? – jasonline

+0

auto_ptr * can * può essere usato per pimpl; non è particolarmente carino perché devi dichiarare e implementare un distruttore. Meglio usare boost :: scoped_ptr (o shared_ptr) che non richiede la definizione di dtor. – MattyT

+0

Non ho problemi a usare std :: auto_ptr per PIMPL. –

6

I puntatori intelligenti sono utilizzati spesso in C++, anche se forse non così spesso come dovrebbero essere. Lo std::auto_ptr ha alcuni problemi (ad esempio, non è possibile utilizzarlo nelle raccolte della Libreria standard), ma ce ne sono molti altri. I più popolari di questi sono the ones that come with the Boost library e che faranno parte del prossimo standard C++: dovresti dare un'occhiata.

Si noti che i puntatori intelligenti riguardano principalmente la proprietà e l'eliminazione di oggetti creati dinamicamente. Se non si dispone di oggetti creati in modo dinamico, che normalmente non vuole puntatori intelligenti:

{ 
    int i = 42; 
    auto_ptr <int> p(& i); // bad! 
} 

Davvero non si vuole fare questo, come quando l'autopointer va fuori del campo di applicazione, si tenterà di eliminare io. Sfortunatamente, non sono stato creato dinamicamente, quindi accadranno cose brutte. Quindi avete bisogno di entrambi i tipi di puntatore, intelligente e normale, nella maggior parte dei programmi C++.

+0

Sì, ne ho sentito parlare da quelli di Boost. È solo che la mia preoccupazione specifica sono le ragioni per le quali non viene utilizzata tutte le volte che vengono usati puntatori ordinari. – jasonline

+3

'auto_ptr' non viene usato molto spesso perché nella maggior parte dei casi sono preferibili quelli di Boost. I puntatori intelligenti * sono * molto spesso utilizzati, e almeno tra molti programmatori, più spesso dei normali puntatori. Perché pensi che i normali puntatori vengano usati più spesso? – jalf

+0

@ jasonline: nel moderno codice C++ non vedo quasi mai i normali puntatori. I puntatori intelligenti sono la norma e i normali puntatori sono l'eccezione. Se vedi qualche codice che ha dei puntatori è molto diffidente nei confronti dell'autore. L'unica volta che vedo i puntatori normali (RAW) nel codice dimostrativo sono tutorial per insegnare agli studenti quali sono i puntatori. –

0

auto_ptr ha un modello di proprietà per l'oggetto a cui punta. Non è possibile avere più rifrazioni sullo stesso oggetto e non è possibile inserirle in contenitori stl e tali - il codice che assomiglia a quello che sta effettivamente trasferendo la proprietà, e andando a causare brutti bug difficili da rintracciare in produzione.

boost shared_ptr è in quasi tutti i casi molto più pratico.

+0

Si dovrebbe fare attenzione anche con gli smartpoint Boost :) – n0rd

+0

Se usato correttamente, perché causerebbe difficoltà a rintracciare i problemi. std :: auto_ptr fa esattamente quello che doveva fare (né più né meno). std :: tr1 :: shared_ptr è un tipo completamente diverso di puntatore intelligente. impara a usare il tipo corretto di puntatore intelligente. –

+2

Mi aspetto che tu non abbia mai un bug, mai, Martin :) – Will

1

Non confondere i puntatori automatici (std :: auto_ptr) con la famiglia di puntatori intelligenti (in particolare std :: auto_ptr, boost :: scoped_ptr e boost :: shared_ptr).

Non uso quasi mai i puntatori automatici perché, la maggior parte delle volte, preferisco usare riferimenti. L'unica volta che faccio è per le variabili membro che non possono essere istanziate nel costruttore dell'oggetto.

Al contrario, puntatori intelligenti sono molto potenti, ma che non è la tua domanda, credo :)

1

vantaggi è che per un utilizzo semplice, fanno il loro lavoro.

void foo() { 
    std::auto_ptr<int> bar(new int); 
    // do the stuff that potentially throw 

} // the auto_ptr destructor will call delete here 

Lo svantaggio è che, non appena a fuggire da questa semplice utilizzo, si colpisce i cattivi semantica di auto_ptr.

std::auto_ptr<int> foo(new int); 
std::auto_ptr<int> bar = foo; // foo is changed here! It does not have ownership anymore. 

Faresti meglio a usare unique_ptr e shared_ptr che hanno buone semantica, e che sono disponibili in boost ::, e sarà disponibile in std :: nel prossimo standard C++

0

Il racconto: std :: auto_ptr non può essere condiviso, i puntatori regolari possono.

E poi c'è Boost.SmartPointer

1

Forse il più grande motivo sul perché non è ampiamente utilizzato:

Lo std :: auto_ptr ha un enorme svantaggio: non può essere copiato senza distruzione. Quando hai bisogno di fare una copia di un puntatore automatico, l'istanza originale viene distrutta. Ciò significa che puoi avere una sola copia dell'oggetto in qualsiasi momento. Ciò significa anche che auto_ptr non può essere utilizzato con contenitori standard, come vettore, deque, elenco, set e mappa. In effetti, difficilmente può essere utilizzato in qualsiasi classe che si basa sulla costruzione di copie.

Inoltre, auto_ptr non è sicuro, poiché nulla impedisce di eseguire una copia accidentalmente. E se lo fai, distruggi la copia originale. Inoltre, alcuni compilatori C++ meno conformi agli standard consentono di memorizzare gli oggetti dichiarati in un auto_ptr e di usarli senza includere mai la definizione completa della classe. Ciò comporta sempre una perdita di memoria.

1

La principale ragione d'essere per auto_ptr è trasferire la proprietà in maniera eccezionalmente sicura. Anche se la maggior parte delle persone la usa come boost: scoped_ptr.

L'utilizzo principale è per le funzioni che restituiscono utilizzando i puntatori di oggetti come parametri o valori di ritorno.

Ad esempio, una funzione di fabbrica

std::auto_ptr<MyClass> createMyClass(MyClass::Type type) { 
    if (type == MyClass::TypeOne) { 
     return std::auto_ptr(new MyClassOne); 
    } 
    else { 
     return std::auto_ptr(new MyClassTwo); 
    } 
} 


void foo() { 
    std::auto_ptr<MyClass> myc = createMyClass(MyClass::TypeOne); 

    // use myc 
} 

Anche se questo codice è molto semplice e senza eccezioni dovrebbe essere gettato se eccezioni sono gettati myc gestisce in modo corretto, in cui fare questo con i puntatori prime sarebbe difficile.

boost :: shared_ptr può essere utilizzato anche, ma questo fornisce più funzionalità di quanto richiesto, inoltre indica che ci si aspetta che l'oggetto sia condiviso. Dove con auto_ptr è più semplice e stai affermando chiaramente che stai trasferendo la proprietà.

Mi è stato detto recentemente su boost :: unique_ptr che sembra avere lo stesso utilizzo di auto_ptr senza gli svantaggi.

vedere best practice when returning smart pointers per ulteriori informazioni

0

Il auto_ptr può essere used for multiple purposes, ma penso che sia il miglior uso è uno strumento per l'assegnazione degli oggetti sul mucchio e di farle deallocate quando gli ambiti dello stack frame si esce.

IMHO l'unico reale problema con auto_ptr è il nome. Le persone lo guardano e pensano che sia un puntatore intelligente, che ovviamente non lo è.

Se lo chiamassimo qualcosa come AutoDelete<T> forse avremmo diversi tipi di discussioni.:-)

Problemi correlati