[C++] Vector of pointers: hoe alloceren?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Brent
  • Registratie: September 2001
  • Laatst online: 15-10 20:20
Vanwege geheugengebruik, moet ik een grote datastructuur in mn program definiëren als een pointer en dan later alloceren met het new-keyword, en vervolgens een paar methodes van die class aanroepen.

Nu heb ik een paar van die structuren die allemaal op precies hetzelfde punt en dezelfde manier aangeroepen moeten worden. Omwille van de leesbaarheid wilde ik daarom die pointers in een tijdelijke list stoppen, op deze wijze:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mijnclass.h:

DataStruc* data0;
DataStruc* data1;
DataStruc* data2;

mijnclass.cc:

mijnclass::mijnclass(){
std::vector<DataStruc*> lijst;
lijst.push_back(data0);
lijst.push_back(data1);
lijst.push_back(data2);
for (int i = 0; i < lijst.size(); i++) {
    lijst[i] = new DataStruc("double");
    lijst[i]->ZomaarWat(mResolution, mHalfSize, mPosition);
    lijst[i]->Methodes(mOrigin);
}
}


Dit gaat echter fout. Ik denk omdat push_back kopieert, en ik dus keurig netjes de kopien instel, maar als ik later elders in het programma data0 aanroep, heb ik nog steeds de (ongeinitialiseerde) class te pakken.

Ik kom er echt niet uit hoe ik het kan oplossen, behalve de lijst weg te halen, en gewoon de code in de for-loop te dupliceren per lijst. Omdat dat toch wat vies is, vraag ik het hier effe: hoe kan ik dit voor elkaar krijgen?

Humanist | Kernpower! | Determinist | Verken uw geest | Politiek dakloos


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Waarom wil je die data0, data1, etc gebruiken? Op dit moment stop je deze ongeinitialiseerde pointers in een lijst, en overschrijf je ze vervolgens.

Je kunt de pointers in je lijst (die je met new() geinitialkiseerd hebt) gewoon elders in je programma gebruiken. Die data0 etc, zijn loze variabelen in je programma.

[ Voor 7% gewijzigd door EddoH op 09-03-2015 16:33 ]


Acties:
  • 0 Henk 'm!

  • Brent
  • Registratie: September 2001
  • Laatst online: 15-10 20:20
data0,1,2 worden elders gebruikt (we hebben nogal wat state, klopt, niets aan te doen), de lijst niet. Het doel is dus wat ik met de lijst alle data op dezelfde wijze wil initialiseren (dat vergt nogal wat method calls), en dat die dan netjes bereikbaar zijn onder data0,1,2.

Op de een of andere manier moet ik dus niet de pointers kopieren (als dat inderdaad de reden is), maar ik google nu al 2 uur en kom er niet uit. Is de enige oplossing dan echt gewoon het blok in de for 3 keer pasten en s/lijst[i]/datax/g?

Humanist | Kernpower! | Determinist | Verken uw geest | Politiek dakloos


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15-10 02:34

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom heb je in de header niet gewoon een DataStruc* data[3]; ?

Het kan overigens nog steeds wel, door pointers te maken naar die pointers. Maar ik zou in plaats daarvan dan gewoon achteraf de lijst kopiëren naar de relevante datamembers ipv zorgen dat de lijst de datamembers spiegelt. Kost je net zoveel code - in plaats van dat je voor de loop steeds push_back aanroept, doe je na de loop assignments.

[ Voor 19% gewijzigd door .oisyn op 09-03-2015 17:00 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • casparvl
  • Registratie: Oktober 2010
  • Niet online
Ik weet vrij zeker dat je push_back inderdaad de pointers kopieert. Met de new-functie verander je dan de pointers in je lijst, maar dus niet de originele pointers data0, data1, data2 etc.
Zoals .oisyn al zegt zou je dit waarschijnlijk kunnen 'oplossen' door pointers te maken naar de pointers en die in je lijst te duwen. Dus iets als
std::vector<DataStruct**> lijst;
lijst.push_back(&data0)
lijst.push_back(&data1)
etc.
Je lijst bestaat dan uit pointers naar de pointers (i.e. pointers naar de DataStruct*). Nu kun je dus de oorspronkelijke pointers wijzigen. Heb 't niet getest, maar zal denk ik dan zijn met
for(...)
*lijst[i] = new DataStruct(...);

Wat ik niet helemaal begrijp is waarom je niet gewoon een initialisatiefunctie maakt die alle stappen op je DataStruct doet. Dus bijv.
InitDataStruct(DataStruct&* data)
{
data = new DataStruct(...)
data->ZomaarWat(...)
data->ZomaarWatAnders(...)
}
Die kun je dan heerhaaldelijk aanroepen op al je data objecten.
InitDataStruct(data0);
InitDataStruct(data1);
etc.
Dat is net zo lang als alle push-backs afzonderlijk doen...
Merk overigens op dat het argument van de functie wel een reference-to-pointer moet zijn, anders heb je hetzelfde probleem als met je lijst (dat bij het aanroepen van de functie de pointer gekopieerd wordt, die veranderd wordt met nieuw, maar het origineel 'leeg' blijft).

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15-10 02:34

.oisyn

Moderator Devschuur®

Demotivational Speaker

Note: een ref-to-ptr definieer je zo: DataStruct*&
Je hebt de * en & dus verkeerd om (tip: lees altijd van rechts naar links)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • casparvl
  • Registratie: Oktober 2010
  • Niet online
Oeps... Thanks voor de correctie, anders zou ik 'm nog van de regen in de drup helpen ;-)

By the way, Brent, ik kom er net achter dat ik je volgens mij ken. Heb jij op 't AMC een masterstage gelopen...? If so, dan zaten we op dezelfde afdeling ;-)

Acties:
  • 0 Henk 'm!

  • Brent
  • Registratie: September 2001
  • Laatst online: 15-10 20:20
.oisyn schreef op maandag 09 maart 2015 @ 16:47:
Waarom heb je in de header niet gewoon een DataStruc* data\[3]; ?
Leesbaarheid.
Het kan overigens nog steeds wel, door pointers te maken naar die pointers. Maar ik zou dan gewoon achteraf de lijst kopiëren naar de relevante datamembers ipv zorgen dat de lijst de datamembers spiegelt. Kost je net zoveel code - in plaats van dat je voor de loop steeds push_back aanroept, doe je na de loop assignments.
Punt is dat ik in dit scenario dan weer vrij vaak (voor ongeveer 5 methods) die pointers naar pointers moet maken, als ik je goed begrijp tenminste.
casparvl schreef op maandag 09 maart 2015 @ 17:03:

Wat ik niet helemaal begrijp is waarom je niet gewoon een initialisatiefunctie maakt die alle stappen op je DataStruct doet.
Hier was ik net mee begonnen, werkte ook niet, totdat je me het concept ref-to-ptr introduceerde. Het lijkt te werken zo _/-\o_
casparvl schreef op maandag 09 maart 2015 @ 17:10:
Oeps... Thanks voor de correctie, anders zou ik 'm nog van de regen in de drup helpen ;-)

By the way, Brent, ik kom er net achter dat ik je volgens mij ken. Heb jij op 't AMC een masterstage gelopen...? If so, dan zaten we op dezelfde afdeling ;-)
Ha, dag Caspar ;) Hoe is het in Amsterdam?

[ Voor 16% gewijzigd door Brent op 09-03-2015 17:11 ]

Humanist | Kernpower! | Determinist | Verken uw geest | Politiek dakloos


Acties:
  • 0 Henk 'm!

  • casparvl
  • Registratie: Oktober 2010
  • Niet online
Goed hoor! Zelden zo iets toevalligs meegemaakt, maar ik dacht: de naam Brent zie je nou niet super vaak. En toen je profiel ook nog zei dat je nu in Lyon zat dacht ik: dat kán bijna niet missen ;-) Succes met je programmeerwerk!

Overigens, misschien dat dit nog leuke achtergrond is, over pointers to pointers, references to pointers, wanneer ze nuttig zijn, etc

http://www.codeproject.co...-and-Reference-to-Pointer

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15-10 02:34

.oisyn

Moderator Devschuur®

Demotivational Speaker

Want data[0], data[1], ... is minder leesbaar dan data0, data1, etc :?
Of is het eigenlijk aap, noot, mies, ...

[ Voor 9% gewijzigd door .oisyn op 09-03-2015 17:19 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Brent
  • Registratie: September 2001
  • Laatst online: 15-10 20:20
casparvl schreef op maandag 09 maart 2015 @ 17:17:
Goed hoor! Zelden zo iets toevalligs meegemaakt, maar ik dacht: de naam Brent zie je nou niet super vaak. En toen je profiel ook nog zei dat je nu in Lyon zat dacht ik: dat kán bijna niet missen ;-) Succes met je programmeerwerk!

Overigens, misschien dat dit nog leuke achtergrond is, over pointers to pointers, references to pointers, wanneer ze nuttig zijn, etc

http://www.codeproject.co...-and-Reference-to-Pointer
Dank. Een ding is zeker, ik zal het gebruik hiervan proberen te minimaliseren ;)
.oisyn schreef op maandag 09 maart 2015 @ 17:18:
[...]

Of is het eigenlijk aap, noot, mies, ...
Uiteraard ;)

Humanist | Kernpower! | Determinist | Verken uw geest | Politiek dakloos


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Brent schreef op maandag 09 maart 2015 @ 17:10:

[...]

Punt is dat ik in dit scenario dan weer vrij vaak (voor ongeveer 5 methods) die pointers naar pointers moet maken, als ik je goed begrijp tenminste.
Vologens mij begrijp je het niet geheel. Je hoeft geen 'pointers naar pointers' te maken. Je geeft je argument (je pointer) by reference aan de init functie en initialiseert deze pointer vervolgens binnen de functie:

C++:
1
2
3
4
5
6
7
8
9
void initMyDataStruct(DataStruc*& aDataStruct) 
{
  aDataStruct = new DataStruc(...);

  //andere init methods...
}

//pass by reference
 initMyDataStruct(data0);


Vervolgens kan je deze geinitialiseerde pointers alsnog in een lijst gooien om er naderhand makkelijk gemeenschappelijke calls op aan te roepen.

[ Voor 6% gewijzigd door EddoH op 10-03-2015 09:36 ]


Acties:
  • 0 Henk 'm!

  • Brent
  • Registratie: September 2001
  • Laatst online: 15-10 20:20
EddoH schreef op dinsdag 10 maart 2015 @ 09:35:
[...]


Vologens mij begrijp je het niet geheel. Je hoeft geen 'pointers naar pointers' te maken. Je geeft je argument (je pointer) by reference aan de init functie en initialiseert deze pointer vervolgens binnen de functie:

C++:
1
2
3
4
5
6
7
8
9
void initMyDataStruct(DataStruc*& aDataStruct) 
{
  aDataStruct = new DataStruc(...);

  //andere init methods...
}

//pass by reference
 initMyDataStruct(data0);


Vervolgens kan je deze geinitialiseerde pointers alsnog in een lijst gooien om er naderhand makkelijk gemeenschappelijke calls op aan te roepen.
Maar dit was niet de suggestie van .oisyn volgens mij. Met ref-to-ptr is het probleem inderdaad al opgelost zoals je kunt lezen ;)

Humanist | Kernpower! | Determinist | Verken uw geest | Politiek dakloos


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Ah, my bad. Je opmerking was inderdaad op een andere suggestie gericht.
Overigens zou ik het verder ook zo doen als .oisyn aangaf: initialiseren vanuit een lijst en vervolgens aan de relevante members assignen.

[ Voor 8% gewijzigd door EddoH op 10-03-2015 10:22 ]

Pagina: 1