Ho sentito dire che auto_ptr
è deprecato in C++ 11. Qual è la ragione di questo?Perché auto_ptr è deprecato?
Inoltre mi piacerebbe sapere la differenza tra auto_ptr
e shared_ptr
.
Ho sentito dire che auto_ptr
è deprecato in C++ 11. Qual è la ragione di questo?Perché auto_ptr è deprecato?
Inoltre mi piacerebbe sapere la differenza tra auto_ptr
e shared_ptr
.
La sostituzione diretta per auto_ptr
(o la cosa più vicina ad uno comunque) è unique_ptr
. Per quanto riguarda il "problema", è piuttosto semplice: auto_ptr
trasferisce la proprietà quando viene assegnata. unique_ptr
trasferisce anche la proprietà, ma grazie alla codifica della semantica del movimento e alla magia dei riferimenti rvalue, può farlo in modo notevolmente più naturale. Inoltre "si adatta" al resto della libreria standard in modo considerevolmente migliore (anche se, in tutta onestà, parte di ciò è dovuto al fatto che il resto della libreria cambia per adattarsi alla semantica del movimento invece di richiedere sempre la copia).
Il cambiamento di nome è anche (IMO) un benvenuto uno - auto_ptr
in realtà non vi dice molto su quello che si tenta di automatizzare, mentre unique_ptr
è una descrizione abbastanza ragionevole (se terso) di ciò che è previsto.
Solo una nota sul 'auto_ptr' nome [è Auto \ _ptr deprecato?]: Auto suggerisce automatico come nella variabile automatica e fa riferimento a una cosa che "auto_ptr' fa: distrugge la risorsa gestita nel suo distruttore (quando esce dal campo di applicazione). –
Ulteriori informazioni: Ecco la spiegazione ufficiale per la deprecazione di 'auto_ptr': http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1856.html#20.4.5%20-% 20Class% 20template% 20auto_ptr –
@HowardHinnant documento interessante! è strano nel senso che se std :: sort() ha una specializzazione per std :: unique_ptr per usare la semantica del movimento come necessario. Mi chiedo perché std :: sort() non possa essere specializzato per std :: auto_ptr per correggere il problema di copia menzionato nel doc. Grazie in anticipo. – Hei
shared_ptr
possono essere stoccati all'interno di contenitori. auto_ptr
no.
BTW unique_ptr
è davvero il auto_ptr
sostituzione diretta, combina le migliori caratteristiche di entrambi std::auto_ptr
e boost::scoped_ptr
.
Ho trovato le risposte esistenti grandiose, ma dal PoV dei puntatori. IMO, una risposta ideale dovrebbe avere la risposta prospettica dell'utente/programmatore.
Per prima cosa (come sottolineato da Jerry Coffin nella sua risposta)
shared_ptr: Se siete preoccupati per la liberazione di risorsa/memoria E se si dispone di più di una funzione che potrebbe utilizzare l'oggetto AT-DIFFERENT volte, quindi andare con shared_ptr.
Da DIFFERENT-Times, pensare a una situazione in cui l'oggetto-ptr è memorizzato in più strutture dati e successivamente acceduto. Più thread, ovviamente, è un altro esempio.
unique_ptr: Se tutto ciò che ti interessa è liberare memoria, e l'accesso all'oggetto è SEQUENTIAL, quindi vai a unique_ptr.
Per SEQUENTIAL, voglio dire, in qualsiasi punto l'accesso sarà accessibile da un contesto. Per esempio. un oggetto che è stato creato e utilizzato immediatamente dopo la creazione dal creatore. Dopo la creazione, l'oggetto viene memorizzato nella struttura dati FIRST. Quindi, l'oggetto viene distrutto dopo la struttura dati ONE o spostato nella struttura dati SECONDO.
Da questa riga, farò riferimento a shared/unique _ptr come puntatori intelligenti. (auto_ptr è anche smart-pointer BUT a causa di difetti nella sua progettazione, per cui sono deprecati, e che penso indicherò nelle righe successive, non dovrebbero essere raggruppati con smart-pointer.)
ragione più importante per spiegare perché auto_ptr è stata sconsigliata a favore di smart-pointer è assegnazione semantica Se non fosse stato per questo motivo, avrebbe aggiunto tutte le nuove chicche della semantica move al auto_ptr invece di deprecarlo. Dato che la semantica del compito era la caratteristica più sgradita, volevano che quella funzione andasse via, ma dal momento che c'è del codice scritto che usa quella semantica, (che il comitato degli standard non può cambiare), hanno dovuto lasciare andare auto_ptr, invece di modificandolo.
Dal link: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
Tipo di assegnazioni supportato da unqiue_ptr
Da: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
Tipo di assegnazioni supportate da auto_ptr
Ora venendo al motivo per cui l'assegnazione di copia era così antipatico, ho questa teoria:
Il comportamento involontario è davvero sgradito e quindi l'antipatia per l'auto_ptr.
(Per il 3,1415926536% di programmatori che intenzionalmente vogliono trasferire la proprietà C++ 11 ha dato loro std :: move(), che ha reso chiara la loro intenzione per tutti gli stagisti che leggeranno e manterranno il codice .)
Dato che ** non ** mai ** desidera due valori 'auto_ptr' che puntano allo stesso oggetto (dato che non danno la proprietà condivisa, il primo a morire lascerà l'altro con un'eredità letale, questo vale anche per' unique_ptr 'utilizzo), puoi suggerire _what was_ intended in quei restanti 96,8584073465% di tutti gli usi? –
Non posso parlare per tutti loro, ma suppongo che, penserebbero * che la proprietà dell'oggetto venga * spostata * e NON solo duplicata, che è errata. –
"Le ricerche sono state mostrate" :-) – deworde
ancora un altro assumere spiegare la differenza ....
Funzionalmente, C++ 11 del std::unique_ptr
è "fisso" std::auto_ptr
: entrambi sono adatti quando - in qualsiasi momento durante l'esecuzione - dovrebbe esserci un singolo proprietario di puntatore intelligente per un oggetto puntato.
La differenza cruciale è in copia-costruzione o l'assegnazione di un altro puntatore intelligente non-scadenza, indicata sulle =>
righe sotto:
std::auto_ptr<T> ap(...);
std::auto_ptr<T> ap2(get_ap_to_T()); // take expiring ownership
=> std::auto_ptr<T> ap3(ap); // take un-expiring ownership ala ap3(ap.release());
ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL
std::unique_ptr<T> up(...);
std::unique_ptr<T> up2(get_up_to_T()); // take expiring ownership
=> std::unique_ptr<T> up3(up); // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up)); // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release()); // EXPLICIT code allowed
Sopra, ap3
tranquillamente "ruba" la proprietà di *ap
, lasciando ap
set a nullptr
, e il problema è che può accadere troppo facilmente, senza che il programmatore abbia pensato alla sua sicurezza.
Ad esempio, se un class
/struct
ha un membro std::auto_ptr
, quindi fare una copia di un'istanza sarà release
il puntatore dall'istanza da copiare: questa è la semantica strani e pericolosamente fuorviante in quanto di solito la copia di qualcosa di non modificarlo. È facile per l'autore della classe/struct trascurare il rilascio del puntatore quando ragiona su invarianti e stato, e conseguentemente accidentalmente tenta di dereferenziare smart-pointer mentre è nullo, o semplicemente non ha ancora l'accesso/la proprietà previsti dei dati puntati.
auto_ptr tranquillamente "ruba" la proprietà +1 – camino
auto_ptr non può essere utilizzato nei contenitori STL perché ha un costruttore di copia che non soddisfa i requisiti del contenitore CopyConstructible. unique_ptr non implementa un costruttore di copie, quindi i contenitori utilizzano metodi alternativi. unique_ptr può essere utilizzato in contenitori ed è più veloce per gli algoritmi standard rispetto a shared_ptr.
#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>
using namespace std;
int main() {
cout << boolalpha;
cout << "is_copy_constructible:" << endl;
cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;
vector<int> i_v;
i_v.push_back(1);
cout << "i_v=" << i_v[0] << endl;
vector<int> i_v2=i_v;
cout << "i_v2=" << i_v2[0] << endl;
vector< unique_ptr<int> > u_v;
u_v.push_back(unique_ptr<int>(new int(2)));
cout << "u_v=" << *u_v[0] << endl;
//vector< unique_ptr<int> > u_v2=u_v; //will not compile, need is_copy_constructible == true
vector< unique_ptr<int> > u_v2 =std::move(u_v); // but can be moved
cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;
vector< shared_ptr<int> > s_v;
shared_ptr<int> s(new int(3));
s_v.push_back(s);
cout << "s_v=" << *s_v[0] << endl;
vector< shared_ptr<int> > s_v2=s_v;
cout << "s_v2=" << *s_v2[0] << endl;
vector< auto_ptr<int> > a_v; //USAGE ERROR
return 0;
}
>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
vector< auto_ptr<int> > a_v; //USAGE ERROR
^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3
Possibile duplicato (http://stackoverflow.com/questions/2404115/is-auto-ptr-deprecated) – malat