/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Containers og pointers
Fra : Socketd


Dato : 10-06-03 00:28

I forbindelse med sidste indlæg kom jeg lige i tanke om dette:

Når du nu opretter et objekt på heap'en (med new) og dette objekt kan
blive medlem af flere container klasser, hvordan er det så smartest at
behandle sletning af dette objekt?
Du kan jo selvfølgelig forsøge at huske at kalde, noget ala removeXXX,
ved alle de forskellige Cklasser, men vil det være meget fyfy at lave en
vector i klassen/objektet som indeholder function-pointers til de
removeXXX funktioner i alle container klasser, hvor opjektet befinder
sig? Så behøver du jo ikke fra container klassens siden være bange for
at delete et objekt, der allerede er deleted eller bruge et ojbekt, der
ikke findes længere?

mvh
socketd

 
 
Decker (10-06-2003)
Kommentar
Fra : Decker


Dato : 10-06-03 19:09

[Socketd <db@traceroute.dk> wrote:]

>Når du nu opretter et objekt på heap'en (med new) og dette objekt kan
>blive medlem af flere container klasser, hvordan er det så smartest at
>behandle sletning af dette objekt?

Meget meget forsigtigt!

Først skal du gøre det klart for dig selv, om du vil (1) lave en "slet
mig" funktion på objektet, som så skal sørge for at "informere"
container klasserne at "nu sletter jeg mig selv", og afvente at alle
container klasserne har ryddet objektet fra deres lister, førend
objektet kan slette sig selv.
Eller (2) en "udestående" funktion, som får besked på at "slet dette
objekt", og skal derefter sørge for at kalde alle container klasserne
med "fjern dette objekt fra din liste hvis du har det", for til sidst at
slette objektet.

Forresten er det (almindelig) C++, eller det nyere C# du bruger? Jeg går
ud fra at det er C++.

BTW: Hvis du ikke kender "C++ FAQ Lite" så får du den lige her;
"http://www.parashift.com/c++-faq-lite/". Den er rigtig god at kikke i,
og lære nogle "interessante" kode konstruktioner.

>Du kan jo selvfølgelig forsøge at huske at kalde, noget ala removeXXX,
>ved alle de forskellige Cklasser, men vil det være meget fyfy at lave en
>vector i klassen/objektet som indeholder function-pointers til de
>removeXXX funktioner i alle container klasser, hvor opjektet befinder
>sig?

Det vil være meget omstændigt. Lad os sige at der er 10
container-objekter og eet data-objekt, som er blevet "meldt ind" i de 10
container-objekter. Så skal dette ene data-objekt altså bruge 10x
hukommelse for at vide at den er i 10 forskellige container-objekter.

Gang nu ovenstående med 1000 data-objekter eller mere... ;-/

Og om tre måneder laver du en ny container-klasse, så skal du også ind
og ændre data-klassen.

>Så behøver du jo ikke fra container klassens siden være bange for
>at delete et objekt, der allerede er deleted eller bruge et ojbekt, der
>ikke findes længere?

Her bør du bruge "Reference counting". Altså i stedet for at
data-objektet har pointere tilbage til container-objekterne som den
"tror" den er i, så har den i stedet en "reference tæller" som beskriver
i hvor mange container-objekter som data-objektet er refereret fra.

Bemærk at reference tælleren _ikke_ beskriver i _hvilke_
container-objekter referencen er! Læs forslag (2) igen.

Søg på Google efter "C++ Reference Counting" (og lignende søge navne)
for at få mere litteratur/eksempler.

Hvis man bruger "Reference counting", så bør man også skjule (beskytte)
destructor (som minimum) og evt. constructor på disse klasser, således
at man sikrer at reference tælling mod data-objektet altid foretages
igennem kontrollerede funktioner. Følgende er noget her-og-nu tastet
pseudo-kode (som tilfældigvis ligner meget C++, men jeg sikrer mig lige
mod syntax-fejl og ting som ikke kan lade sig gøre i C++.)

class MyReferencedClass
{
public:
static MyReferencedClass* Create();
static void Destroy(MyReferencedClass*);

MyReferencedClass* Referenced();

int GetReferenceCount() { return m_ReferenceCount; }

protected:
MyReferencedClass() {};
~MyReferencedClass() {};
   // Man må ikke destructe objektet, før reference-
   // count er nul! Derfor bør destructor være beskyttet.

private:
int m_ReferenceCount;
};

MyReferencedClass* MyReferencedClass::Create()
{
MyReferencedClass *object = new MyReferencedClass();
object->m_ReferenceCount = 1;
return object;
}

MyReferencedClass* MyReferencedClass::Referenced()
{
++m_ReferenceCount;
return this;
}

void MyReferencedClass::Destroy(MyReferencedClass *obj)
{
//! @todo Test for negative reference-count, which is bad.
if (0 == --m_ReferenceCount)
{
// Only physically delete object, when reference-count
// has reached zero.
delete obj;
}
}

int main(int argc, char *argv[])
{
//MyReferencedClass *obj1 = new MyReferencedClass;
         //<- Compiler error. Constructor is protected.

MyReferencedClass *obj1 = MyReferencedClass::Create();
MyReferencedClass *obj1_igen = obj1->Referenced();

//delete obj1; //<- Compiler error. Destructor is protected.

cout << obj1_igen->GetReferenceCount() << endl;

obj1->Destroy();
obj1 = NULL;

cout << obj1_igen->GetReferenceCount() << endl;

obj1_igen->Destroy();
obj1_igen = NULL;
}

--
/Decker - http://www.planetquake.com/quark - map-editor for Half-Life & more.
q1r3p3x7re_qx@ubgznvy.pbz. E-mail spam-guard: I'm no '1337', so remove/rot13.

Socketd (10-06-2003)
Kommentar
Fra : Socketd


Dato : 10-06-03 20:33

On Tue, 10 Jun 2003 20:08:57 +0200
Decker <q1r3p3x7re_qx@ubgznvy.pbz> wrote:

> Forresten er det (almindelig) C++, eller det nyere C# du bruger? Jeg
> går ud fra at det er C++.

Jep

> Her bør du bruge "Reference counting". Altså i stedet for at
> data-objektet har pointere tilbage til container-objekterne som den
> "tror" den er i, så har den i stedet en "reference tæller" som
> beskriver i hvor mange container-objekter som data-objektet er
> refereret fra.
>
> Bemærk at reference tælleren _ikke_ beskriver i _hvilke_
> container-objekter referencen er! Læs forslag (2) igen.

Aha, altså forslag 2 i samarbejde med reference counting. Egentlig
behøves sidstnævnte vel ikke hvis man bruger forslag 2, men det er jo
smart at have selle på når man kører.

> class MyReferencedClass
> {
> public:
> static MyReferencedClass* Create();
> static void Destroy(MyReferencedClass*);

Jeg ved godt du lige hurtigt har skrevet dette, men bare for at være
sikker spørg jeg lige. Bør/kan Destroy ikke være nonstatic? Og behøver
man egentlig en Create funktion?

mvh
socketd

Decker (10-06-2003)
Kommentar
Fra : Decker


Dato : 10-06-03 21:28

[Socketd <db@traceroute.dk> wrote:]

>> class MyReferencedClass
>> {
>> public:
>> static MyReferencedClass* Create();
>> static void Destroy(MyReferencedClass*);
>
>Jeg ved godt du lige hurtigt har skrevet dette, men bare for at være
>sikker spørg jeg lige. Bør/kan Destroy ikke være nonstatic? Og behøver
>man egentlig en Create funktion?

Det er helt op til dig.

Grunden til at jeg har en Create og Destroy, som begge er static, er at
det giver et ensartet "interface" til at danne og fjerne objekterne.
Hvis nu f.eks. at du havde dette:

class SomeClass
{
public:
SomeClass() {}; // constructor
void Destroy() { delete this; }
protected:
~SomeClass() {}; // destructor
};

Så ville konstruktion og destruktion se sådan ud:

{
SomeClass *obj = new SomeClass; // "new" er standard C++.
obj->Destroy(); // Dette er ikke standard C++ at slette et objekt på,
// normalt bruger man "delete obj;", så det kan
// forvirre andre der læser koden, da de så at "obj"
// blev dannet med "new".
obj = NULL; // Husk lige at "obj" nu ikke peger på et validt objekt.
}

Personligt syntes jeg det er pænere med følgende, da det gerne skulle
"instruere" andre som læser koden, at der ikke direkte er tale om en
normal "new" og "delete" af objektet - at det så m.m. sker inde i disse
to funktioner er en anden snak:

{
SomeClass *obj = SomeClass::Create();
SomeClass::Destroy(obj); // Sætter også obj=NULL før der returneres,
// da "Destroy(SomeClass* &obj);".
}

--
/Decker - http://www.planetquake.com/quark - map-editor for Half-Life & more.
q1r3p3x7re_qx@ubgznvy.pbz. E-mail spam-guard: I'm no '1337', so remove/rot13.

Mogens Hansen (10-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 10-06-03 20:42


> "Socketd" <db@traceroute.dk> wrote in message
news:20030610012745.705323fa.db@traceroute.dk...
> I forbindelse med sidste indlæg kom jeg lige i tanke om dette:

> Når du nu opretter et objekt på heap'en (med new) og dette objekt kan
> blive medlem af flere container klasser, hvordan er det så smartest at
> behandle sletning af dette objekt?

Det kommer an på hvilken opførsel du ønsker.
Skal objektet slettes når sidste reference forsvinder, eller skal alle
referencer fjernes når objektet forsvinder.

Se eventuelt f.eks. Boost Smart Pointer Library
(http://www.boost.org/libs/smart_ptr/index.htm) for nogle ideer og noget
kode der kan bruges direkte.
Kig især på "shared_ptr" og "weak_ptr"

Venlig hilsen

Mogens Hansen



Socketd (10-06-2003)
Kommentar
Fra : Socketd


Dato : 10-06-03 20:59

On Tue, 10 Jun 2003 21:41:30 +0200
"Mogens Hansen" <mogens_h@dk-online.dk> wrote:

> Det kommer an på hvilken opførsel du ønsker.
> Skal objektet slettes når sidste reference forsvinder, eller skal alle
> referencer fjernes når objektet forsvinder.
>
> Se eventuelt f.eks. Boost Smart Pointer Library
> (http://www.boost.org/libs/smart_ptr/index.htm) for nogle ideer og
> noget kode der kan bruges direkte.
> Kig især på "shared_ptr" og "weak_ptr"

Oki, takker

mvh
socketd

Socketd (10-06-2003)
Kommentar
Fra : Socketd


Dato : 10-06-03 22:26

On Tue, 10 Jun 2003 22:28:25 +0200
Decker <q1r3p3x7re_qx@ubgznvy.pbz> wrote:

> Personligt syntes jeg det er pænere med følgende, da det gerne skulle
> "instruere" andre som læser koden, at der ikke direkte er tale om en
> normal "new" og "delete" af objektet - at det så m.m. sker inde i
> disse to funktioner er en anden snak:
>
> {
> SomeClass *obj = SomeClass::Create();
> SomeClass::Destroy(obj); // Sætter også obj=NULL før der returneres,
> // da "Destroy(SomeClass* &obj);".
> }

Ok, nu har jeg noget at arbejde med, jeg takker for hjælpen

mvh
socketd

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408923
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste