[an error occurred while processing this directive] [an error occurred while processing this directive][an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive] (none) [an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive][an error occurred while processing this directive] [an error occurred while processing this directive][an error occurred while processing this directive] [an error occurred while processing this directive][an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive] (none) [an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive][an error occurred while processing this directive]
 
[an error occurred while processing this directive] [an error occurred while processing this directive]
Skåne Sjælland Linux User Group - http://www.sslug.dk Home   Subscribe   Mail Archive   Forum   Calendar   Search
MhonArc Date: [Date Prev] [Date Index] [Date Next]   Thread: [Date Prev] [Thread Index] [Date Next]   MhonArc
 

Re: [PROGRAMMERING] sletning af stl vector indeholdende dynamisk allokeret array



On Fri, Oct 29, 2004 at 12:13:53PM +0200, Hans-Christian Stadler wrote:
...
> int main (int argc, char argv[]) {
> 	typedef vector<str_ptr> myvector;
> 	try {
> 		myvector *vec = new myvector;

Godt eksempel!

Da jeg så det ville jeg lige nævne en fiks lille ting som mange ikke er
klar over:

Istedet for at skrive:

int main(int argc, char argv**) {
  // .... few initializations
  try {
    //  lots of stuff
    //  ...
  } catch (...) {
    std::cerr << "Foo!" << std::endl;
    exit(1);
  }
  return 0;
}

Kan man skrive:

int main(int argc, char argv**) try
{
 // ... few initializations
 //   lots of stuff
 //   ...
} catch (...) {
 std::cerr << "Foo!" << std::endl;
 return 1;
}

Flere pointer:
1) Man kan lave 'try/catc' direkte efter funktions navnet,
   man behøves ikke at have det i det ekstra sæt klammer -
   der er jo ingen grund til at neste flere blokke end højst 
   nødvendigt
2) Ovenstående vil også fange exceptions fra konstruktørerne
   i de først deklarerede variable (ok du havde så ingen i
   dit eksempel)
3) 'return 0' er implicit i slutningen af main
4) 'return 1' kan bruges i den sidste catch, selvom man kunne
   tro at den egentligt står uden for main funktionen - men det
   gør den altså ikke  ;)    Og så gør den iøvrigt det samme
   som exit(1);
  
Men det her har jo alt sammen intet at gøre med hvad der egentligt blev
spurgt om - dit eksempel var et rigtigt godt svar!

Jeg bruger normalt ikke auto_ptr til det, da det giver problemer med
kopiering af elementerne.

Istedet ville jeg lave noget i stil med

------------
template <typename T>
class vector_gc {
public:
 vector_gc(std::vector<T> &v) : v(v) { }
 ~vector_gc() {
  for (std::vector<T>::iterator i = v.begin();
       i != v.end(); ++i) delete *i;
  v.clear(); // ikke nødvendig, men sikrer mod dummefejl
 }
private:
 std::vector<T> &v;
};
------------

Det er en fiks lille 'garbage collector' til vektorer med pointere til
etellerandet som elementer. Når garbage collectorens destruktør kører
(bør køres umiddelbart før vektorens), vil den deallokere de data
vektorens elementer peger på.

Jeg har hugget dit eksempel og brugt den der:

------------
int main (int argc, char argv[]) {
        try {
                do {
			std::vector<std::string*> myvector;
	                vector_gc<std::string*> mgc(myvector);
                        vec.push_back(new string("Bliver"));
                        vec.push_back(new string("jeg"));
                        vec.push_back(new string("leaket"));
                        vec.push_back(new string("??"));
                        for_each(vec.begin(), vec.end(), print());
                        cout << endl;
                } while (true);
        }
        catch (bad_alloc) {
                cerr << "Some string allocation failed" << endl;
                exit(1);
        }
        return 0;
}
------------

Har naturligvis ikke set om noget af det compiler  ;)

Fordelen ved min løsning er, at jeg stadig blot har en vektor af
pointere til en eller anden slags elementer.  Og jeg kan smide den rundt
til andre funktioner som det, de kan bruge elementer eller lade være, og
jeg synes man holder det rimeligt simpelt på den måde.

Når blot man instantierer sin garbage collector umiddelbart efter sin
vector, vil al deallokeringen ske på 'magisk vis' når vektoren alligevel
destrueres (ved slutningen af den blok hvor den er deklareret).

Til gengæld er min løsning uegnet hvis man (som i dit oprindelige
eksempel) også allokerer sin vektor dynamisk.

Den slags 'garbage collection' som mit eksempel bruger, er enormt smart
når man allokerer alle sine containere på stakken.  Og det er ubrugeligt
når man allokerer dynamisk.

Det rette værktøj til det rette job, må det vel være noget med  :)

Der er ihvertfald mange måder at skære den kage på, det er helt sikker
;)

-- 

 / jakob



 
Home   Subscribe   Mail Archive   Index   Calendar   Search

 
 
Questions about the web-pages to <www_admin>. Last modified 2005-08-10, 22:44 CEST [an error occurred while processing this directive]
This page is maintained by [an error occurred while processing this directive]MHonArc [an error occurred while processing this directive] # [an error occurred while processing this directive] *