Newsgroup: it.comp.lang.c++
Titolo: [Curiosità] auto_array

Nel mio codice sono abituato a fare massiccio uso di std::auto_ptr<T> per
garantire la sicurezza rispetto alle eccezioni. Tuttavia all'interno di un
auto_ptr non posso inserire puntatori allocati con new[], poichè il
distruttore richiama delete e non delete[]. Alla fine mi sono deciso ad
implementare la mia "versione array" di auto_ptr (auto_array, per
l'appunto), ma mi chiedo come mai una classe del genere non sia stata
inclusa nella libreria standard.
Esiste forse un modo per adattare auto_ptr ai puntatori ad array? O forse un
auto_array non può essere implementato per via di qualche cavillo tecnico
che io ignoro? O è stata soltanto negligenza da parte dei progettisti della
libreria? (O forse sono semplicemente io a sbagliare nell'utilizzo di
auto_ptr?)
Grazie anticipatamente.



una classe del genere non sia stata inclusa nella libreria standard.
Perche' non puoi usare semplicemente std::vector invece di
un array allocato esplicitamente con new[] ?
Nella implementazione tipica un std::vector e' soltanto un
puntatore ad un'area allocata sullo heap, una dimensione
e una dimensione di allocazione (oppure in alternativa a
questi ultimi due un puntatore alla fine dei dati contenuti
e un puntatore alla fine dell'area allocata).
I casi in cui questo e' molto meno efficiente di una semplice
allocazione sullo heap dovrebbero essere abbastanza rari.
std::vector non ha problemi in caso di exception e offre
funzionalita' spesso utili.
Andrea

 un array allocato esplicitamente con new[] ?
Ottima soluzione! Così semplice che non l'avevo mai considerata!
Mi rimane un dubbio però: nel caso in cui l'array debba essere restituito
all'esterno della funzione il costruttore per copia di vector è molto
pesantuccio...
Si può utilizzare l'approccio
return auto_ptr<vector<T> >(new vector<T>(dimensione));
Personalmente preferisco il più semplice
return auto_array<T>(new T[dimensione]);
(che evita anche la new addizionale) ma a questo punto è solo una questione
di gusti :-D
Comunque continuo a non capire perchè non sia stato inserito anche
auto_array nella libreria standard dato che per implementarlo basta
semplicemente aggiungere due parentesi quadre davanti al delete nel
distruttore di auto_ptr! ;-)
AG75202

distruttore di auto_ptr! ;-)
Credo che la scusa ufficiale sia proprio che c'e' gia'
std::vector che rende raramente giustificabile l'uso di
un puntatore naked ad un array allocato dinamicamente.
HTH
Andrea

 creato direttamente dentro mv.
A questo punto sembri suggerire che nell'esempio in questione di fatto 
venga instanziato un solo vector e non si verifichi nessuna copia. Ma non 
č cosě.
Ad ogni modo, convengo che in generale č meglio "restituire" i container 
tramite parametri reference non-const, perň se proprio si vuole restituire 
un container instaziato localmente senza allocarlo dinamicamente e senza 
che si verifichino copie degli elementi, si potrebbe creare una classe, 
simile come filosofia ad auto_ptr, che contenga un'instanza del container 
ed effettui lo swap nel costruttore:
  template< class T >
  class auto_swap
  {     T data;
        public:
        auto_swap( T& v ) { data.swap(v); }
        auto_swap( auto_swap<T>& v ) { data.swap(v.data); }
        T& data () { return data; }
  };
Restituendo questa classe il container viene "spostato" fuori dalla 
funzione senza riallocazioni e copie degli elementi.
Max

funzione senza riallocazioni e copie degli elementi.
Che vengano create copie in questo caso non e' insito nel linguaggio,
ma una mera questione di QOI. Se ho problemi preferisco pero'
qualcosa di piu' leggibile come passare reference (cosa che offre
anche altri vantaggi come ho gia' detto nel post precedente).
Andrea

 viene costruito un solo vector e non viene fatta nessuna copia.
Vuoi dire che, con la tua versione di g++, i due oggetti ('v' e 'vm') hanno
lo stesso indirizzo?
Con la versione che ho sotto mano (3.0), no, nemmeno compilando con O3.
Proverò con versioni successive.
Mi chiedo una cosa, però, se il compilatore riesce ad ottimizzare al punto
che l'oggetto del main viene costruito prima delle variabili locali della
funzione, non si determina qualche violazione nell'ordine di valutazione
dell'espressioni?
Max

  return std::vector<X>();
In realta' sono consentite entrambe le ottimizzazioni, dette
rispettivamente 'return value optimization' e 'named return value
optimization'. Nel caso descritto da Andrea la variabile v
coinciderebbe con lo spazio allocato per il valore di ritorno. E'
ovviamente necessario garantire che tutte le uscite dalla funzione
restituiscano v.
Ciao,
Nicola

dell'espressioni?
Non ho capito questa obiezione :/
Andrea

 
Se non l'hai capita, probailmente non aveva molto senso. Non era 
un'obiezione, piuttosto una riflessione. Quel che intendevo dire č: mentre 
dal punto di vista sintattico il valore restituito dalla funzione viene 
passato come argomento al costruttore dell'oggetto, non sono autorizzato ad 
assumere che la funzione termini effettivamente prima che il costruttore 
dell'oggetto venga chiamato. (E' un po' controintuitivo.)
Max