webForumDet fria alternativet

Pekare

31 svar · 1 309 visningar · startad av LilleSkutt

LilleSkuttMedlem sedan feb. 2001265 inlägg
#1

Hallå!

Jag har lite problem när jag försöker använda mig av pekare.

Så här gör jag:
<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">
...
bool quit;
char lista[PERSONER][PLATSER][LANGD];
int counter = 0;
int *cPointer;
cPointer = &counter;
...

Jag får ett felmeddelande på raden cPointer = &counter;

Om jag gör likadant i en annan fil o kompilerar funkar det perfa. Vad kan vara fel? Kan det bero på vilka filer man inkluderar eller?

------------------
---
/* LilleSkutt */

SweyMedlem sedan apr. 20003 971 inlägg
#2

Får du ett felmeddelande, ska du alltid skriva vad som står i felmeddelandet.

------------------
- Swey
A hacker from the south

LilleSkuttMedlem sedan feb. 2001265 inlägg
#3

OK, förlåt :)

Kommer inte ihåg exakt vad som stod i felmeddelandet men det var någonting med type name.. :)

------------------
---
/* LilleSkutt */

BeatboxMedlem sedan okt. 20013 217 inlägg
#4

<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">
...
bool quit;
char lista[PERSONER][PLATSER][LANGD];
int counter = 0;
int *cPointer;
cPointer = &counter;
...

----------------------------
Kan du inte göra :

int *cPointer = new int(0)

// BeatBox

SweyMedlem sedan apr. 20003 971 inlägg
#5

Jag tror inte han vill skapa en ny integer, utan peka till en istället.

Det är dock inget fel i koden, så felet beror på något du skrivit tidigare eller på kompilatorn.

------------------
- Swey
A hacker from the south

BeatboxMedlem sedan okt. 20013 217 inlägg
#6

Resultatet blir ju det samma plus att det blir snyggare och effektivare kod. Om man har en variabel som ligger på stacken så kan jag inte finna någon anledning att man vill ta tag i pekaren och sedan sätta värdet på variabeln via pekaren.

// BeatBox

developerMedlem sedan aug. 2001458 inlägg
#7

Resultatet blir ju det samma plus att det blir snyggare och effektivare kod.

Exakt hur menar du att ditt förslag leder till snyggare och effektivare kod?

Du gör en allokering på heapen, vilket inte alls är effektivt (som du påstår). Tvärtom, heapallokeringar är ofta en flaskhals i program och gör att programmen inte skalar på flera CPU:er. Se http://debatt.passagen.se/html/500000000000002/500000000000067/10000000000976502.shtml

Vidare inför du en risk att glömma att deallokera minnet.

Att din kod är snyggare än LilleSkutts förstår håller jag inte alls med om.

Jag håller dock med dig om att det inte är helt lätt att komma på ett fall då man vill peka på en stack-allokerad integer.

BeatboxMedlem sedan okt. 20013 217 inlägg
#8

Stack allokering kan ju bli i princip hur farlig som helst. Pilla på data som ligger på stacken genom en pekare är nog inte världens mest goda idé. I inlägget som du reffererar till så talas det om en heap-hanterare. Antalet CPU:er har väl inget som helst att göra med heap:en. Det tillhör ju inte direkt god programmerings-sed att göra som LilleSkutt gör. Man skapar inte en lokal variabel och sedan en pekare av samma typ och sedan sätter pekaren till den lokala variabeln.

// BeatBox

UlfTMedlem sedan maj 20018 027 inlägg
#9

Angående LilleSkutts programmeringssed avseende pekare, jag tror han försöker köra något övningsexempel som ska illustrera vad pekare är. Det är därför han pekar på en int på stacken. Det övningsmomentet skulle utebli om han allokerade pekaren med "new".

BeatboxMedlem sedan okt. 20013 217 inlägg
#10

Jo... det är ju sant ! :-) Syntaxtiskt är det ju korrekt och borde funka. Kan det inte vara en inställning i miljön angående stacken som orsakar felmeddelanden ? Om man är ny (har varit där en gång själv) så kan man ju tro att man kan t ex returnera pekaren (om det är en funktion förståss) och på så vis komma åt datat i Counter via cPointer vilket blir otroligt fel och kan ge upphjov till de mest konstiga fel. Det kan ju fungera ibland.

// BeatBox

developerMedlem sedan aug. 2001458 inlägg
#11

Stack allokering kan ju bli i princip hur farlig som helst.

Hur menar du då?

Pilla på data som ligger på stacken genom en pekare är nog inte världens mest goda idé.

Tvärtom, en ganska vanlig situation.
Vanligt är att ha en lokal buffert, fylla den med data från någon funktion. Sedan traversera och behandla datat med en pekare in i bufferten.<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">byte Message[some_size];
GetSomeData(Message, sizeof(Message));
byte *cursor = &Message[0];
// Sen accessar man datat med cursor-pekaren

Om man är ny (har varit där en gång själv)...

Om du är en erfaren och duktig C++ programmerare vet du väl vad som är vanliga problem med heapallokerat minne? ;-)

Antalet CPU:er har väl inget som helst att göra med heap:en.

Jovisst, det påverkar prestanda negativt om man inte vet vad en heapallokering egentligen gör...
Man har en och samma addressrymd - oavsett antalet processorer. Så om 4 trådar, körandes på varsin processor, samtidigt free'ar (allokeringen är oftast mycket billigare) minne, måste detta serialiseras (1 processor får jobba, de andra vilar!) - om man inte tänker till. Vilket gör att 3 trådar (processorer) sover medan den 4:e låser minneshanteraren. Hur bra är det att ha 75% CPU-tid outnyttjad? Vidare kan det ge onödiga fragmenteringsproblem. Håller man så mycket arbetsdata som möjligt på stacken, får man mindre av dessa problem. Givetvis är detta inte alltid möjligt - men det är sällan man ser folk optimera med avseende på detta, och det ger dåligt prestanda. Jag har sett flera exempel på detta hos flera företag jag hjälpt med prestandaproblem i system som går live.

Gör man frekventa allokeringar, finns det flera saker man kan göra för att undvika heapmanagern som flaskhals:
- Håll data på stacken, istället för att belasta heapen.
- Ha pooler med allokerat data internt i programmet istället för att allokera och free:a data ofta.
- Minimera antalet heapallokeringar - har du 2 heapallokerade datastrukturer som kan slås ihop är detta oftast effektivare.
- Använd som sista åtgärd en effektiv heapmanager, MP Heap från Platform SDK eller SmartHeap från www.microquill.com

Läs gärna mer på http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngenlib/html/heap3.asp om vanliga problem och lösningar till heapproblem.

Som du säger är det uppenbarligen förkastligt att returnera en pekare till en lokal variabel. Skilj dock detta från att jobba med en pekare till en lokal buffert inom en funktion - något som varken är ovanligt eller riskabelt.

Vidhåller du fortfarande att ditt exempel är effektivare med heapallokering? Isåfall, förklara vad du menar, så visar jag gärna hur jag tänker mig att det fungerar.

Om LilleSkutt vill ha sitt problem löst måste han nog beskriva mer detaljerat vad som gått fel. Där tror jag vi är överens :)

[Redigerat av developer den 07 okt 2001]

BeatboxMedlem sedan okt. 20013 217 inlägg
#12

Allt i världen handlar inte om optimering. Det kostar ju en hel del att buggrätta saker som är halvdant gjorda när produkten är ute hos kund sedan. Eftersom pekare är OTROLIGT klurigt då man är ny programmerare så tycker jag att det är av yttersta vikt att man också lär ut faran med pekare (och dynamisk minnes allokering). Är vi överense på den punkten då ? :-)

// BeatBox

LilleSkuttMedlem sedan feb. 2001265 inlägg
#13

Eftersom pekare är OTROLIGT klurigt då man är ny programmerare...

Japp, det är det verkligen :l

Tack för att ni för en sådan vild diskussion om dem ;)
Även fast jag inte förstår så mycket...

Jag vet inte vad jag gjorde för fel, men om jag istället skrev:
<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">
...
bool quit;
char lista[PERSONER][PLATSER][LANGD];
int counter = 0;
int *cPointer = &counter;
...

funkade det... Vad är eg. skillnaden på de två sätten? :q

Jag har stött på ännu ett problem:
Jag har en klass, som jag sedan ska skapa en array av. Detta går inte, jag får felmeddelandena no match for 'Klassnamn & = Klassnamn *' och candidates are: class Klassnamn & Klassnamn::operator =(const Klassnamn &).

Så här gör jag:
<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">
Klassnamn minArray[5];

minArray[0] = new Klassnamn(parametrar);
...

------------------
---
/* LilleSkutt */

BeatboxMedlem sedan okt. 20013 217 inlägg
#14

Hej LilleSkutt !

Kan det vara så att "new Klassnamn" returnerar en pekare till ditt nya objekt och du måste lagra pekare till din klass i din array ?

// BeatBox

UlfTMedlem sedan maj 20018 027 inlägg
#15

Angående ditt första problem med cPointer etc har jag inga svar. Vore intressant att se om Developer kan belysa det problemet.

Angående problem nr 2 ser det ut som om Beatbox berör lösningen. Jag ser det så här:
<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">Klassnamn minArray[5]; // Du instantierar en array med 5 objekt

minArray[0] = new Klassnamn(parametrar); // Här försöker du mha new instansiera ett objekt och sedan returnera en pekare till ett objektDu har alltså blandat ihop objekt med pekare till objekt, samt att du tycks instantiera objekt två gånger om man kan uttrycka det så.

LilleSkuttMedlem sedan feb. 2001265 inlägg
#16

Hmm, ok... Så jag sätter bara en liten stjärna (*) framför minArray[5]; för att lösa det eller?
<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">
Klassnamn* minArray[5];
...

------------------
---
/* LilleSkutt */

SweyMedlem sedan apr. 20003 971 inlägg
#17

"Så jag sätter bara en liten stjärna"
Ja, om du vill allokera klasserna på heapen. Om du vill allokera klasserna på stacken räcker det med den första raden (utan stjärna).

Allokerar du klasserna på heapen frigörs inte utrymmet automatiskt. Då måste du ta bort det med delete, när du är klar.

------------------
- Swey
A hacker from the south

[Redigerat av Swey den 08 okt 2001]

FridolfMedlem sedan aug. 2001723 inlägg
#18

Använd inte new bara.

developerMedlem sedan aug. 2001458 inlägg
#19

Om jag förstått rätt, så fungerade följande för LilleSkutt:<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">int counter = 0;
int *cPointer;
cPointer = &counter;

Men följande fungerade inte:<font size="1" face="Verdana, Arial, Helvetica, sans-serif">Kod:<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#666600">int counter = 0;
int *cPointer = &counter;

Dessa 2 exempel är likvärdiga. Kompilatorbug är knappast troligt (vilken kompilator?), så jag gissar på att LilleSkutt gjort något misstag första gången.

SweyMedlem sedan apr. 20003 971 inlägg
#20

Nej, Developer, tvärt om - det första fungerade inte, det andra fungerade.

------------------
- Swey
A hacker from the south

133 ms totalt · 3 externa anrop · v20260731065814-full.2b84b982
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
130 ms — hämta tråd, inlägg och bilagor (db)