Newsgroup: it.comp.lang.c++
Titolo: Oggetto creato inutilmente?

Ecco un'altro dubbio che mi e' sorto sempre in merito alle chiamate a
costruttori e distruttori con l'uso dei contenitori STL.
#include <iostream>
#include <vector>
class A {
 public :
  A() {std::cout << "Ctor" <<  " " << this << std::endl;};
  A(const A&r) {std::cout << "Copy Ctor" <<  " " << this << std::endl;};
  ~A() {std::cout << "Dtor" <<  " " << this << std::endl;};
};
int main() {
 vector<A> z(1);
 std::cout << "reserve()" << std::endl;
 z.reserve(2);
 std::cout << "resize()" << std::endl;
 z.resize(2);
 std::cout << "End Main" << std::endl;
 return 0;
}
Ottengo il seguente output:
Ctor 0xc73fa8
Copy Ctor 0xc743c0
Dtor 0xc73fa8
reserve()
Copy Ctor 0xc743c8
Dtor 0xc743c0
resize()
Ctor 0xc73fac
Copy Ctor 0xc73f4c // Viene creato
Copy Ctor 0xc743c9
Dtor 0xc73f4c // E subito distrutto.
Dtor 0xc73fac
End Main
Dtor 0xc743c8
Dtor 0xc743c9
Il compilatore, non dovrebbe creare soltanto un nuovo oggetto (0xc743c9)
evitando la creazione e distruzione di 0xc73f4c?
Grazie

Piu' che il compilatore e' l'implementazione della libreria, che
comunque e' libera di fare quante copie vuole. Per dire se questa copia
e' effettivamente inutile bisognerebbe esaminare il codice di <vector>.
Ciao,
Nicola

 evitando la creazione e distruzione di 0xc73f4c?
Rispondo a che a questo post: resize crea quell'oggetto temporaneo per
allocare memoria per le locazioni che ancora non contengono oggetti:
Cioe', se creo un vector di 2 elementi e lo ridimensiono a 5, i 3 in
aggiunta vengono inizializzati con l'oggetto temporaneo creato, mentre le
altre 2 locazioni vengono riempite dai precedenti valori... ovviamente non
si puo' piu fare affidamento sui vecchi indirizzi degli elementi perche'
resize sposta gli elementi stessi e per evitare tali inconvenienti bisogna
usare reserve il quale alloca gia in precedenza la memoria per gli elementi.
Pero' noto che resize crea un'altro oggetto che sembra essere inutile.
Infatti dato il seguente sorgente:
#include <iostream>
#include <vector>
class A {
 public :
  A() {std::cout << "Ctor " << this << std::endl;};
  A(const A& r) {std::cout << "Copy Ctor " << this << " &r = " << &r <<
std::endl;};
  ~A() {std::cout << "Dtor " << this << std::endl;};
};
int main() {
 vector<A> z(1);
 std::cout << "riserve()" << std::endl;
 z.reserve(2);
 std::cout << "resize()" << std::endl;
 z.resize(2);
 std::cout << "End Main" << std::endl;
 return 0;
}
Ottengo il seguente output:
// Ok
Ctor 0xbabfa8
Copy Ctor 0x303c0 &r = 0xbabfa8
Dtor 0xbabfa8
// Ok
riserve()
Copy Ctor 0x303c8 &r = 0x303c0
Dtor 0x303c0
resize()
Ctor 0xbabfac // Oggetto temporaneo per inizializzare (?)
Copy Ctor 0xbabf4c &r = 0xbabfac // Che inizializza un'altro oggetto
temporaneo?!?!?
Copy Ctor 0x303c9 &r = 0xbabf4c // Il quale inizializza la locazione di
memoria che resize() richiede (essendo resize(2) ed v.size() == 1 in quanto
reserve non modifica la dimensione del vector)
Dtor 0xbabf4c // Distruzione dell'oggetto temporaneo
Dtor 0xbabfac // Idem
// Ok
End Main
Dtor 0x303c8
Dtor 0x303c9
Grazie

 [cut]
Perchè non dai una lettura al codice della libreria? Io faccio così ogni
volta che qualcosa non mi è chiaro: nessun spiegazione è più completa del
codice sorgente stesso.
Se hai la GNU/libstdc++v3 all'interno del codice sorgente di gcc-3.4.x, puoi
trovare ciò che ti serve in:
path_al_sorgente_gcc-3.4.x/libstdc++-v3/include/std/std_vector.h
che include i seguenti due (e altro ancora):
path_al_sorgente_gcc-3.4.x/libstdc++-v3/include/bits/stl_vector.h
path_al_sorgente_gcc-3.4.x/libstdc++-v3/include/bits/vector.tcc
Buon lavoro,
fabio de francesco
(fabiomdf)
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/