Gå til innhold

Hvordan får jeg gjort denne klassen mer elegant?


Anbefalte innlegg

Hei, har skrevet denne klassen som håndterer en liste med waypoints, og uten at jeg er den mest drevne i c++ så synes jeg den virker litt klumsette ... ble mye repetering liksom.

 

uansett det jeg da prøvde meg på en stund men som jeg ga opp var å returnere coord structen på array[index] framfor å returnere lat og lon separat som det er nå, det jeg da gjorde var:

 

coord current {
return waypoints[index];
}

 

og dette fungerte jo (eller det kompilerte) men så satte jeg meg fast når det kom til å bruke dette, mistenker at det på noen måte skal pekes til strukturen som returneres eller noe men klarte ikke å få til dette da..

 

uansett, om noen kunne hjelpe meg å få til dette samt noen andre forbedringer om det er noen hadde det vært flott!

 

P.S: Ikke noen vits i å bry seg om overflows osv ATM, det er en smal sak å fikse :)

 

 

typedef struct {
float lat;
float lon;
} coord;
class waypoints {
private:
 coord waypoints[MAX];
 int index;
public:
 float currentLat() {
return waypoints[index].lat;
 }
 float currentLon() {
return waypoints[index].lon;
 }
 float nextLat() {
return waypoints[index + 1].lat;
 }
 float nextLon() {
return waypoints[index + 1].lon;
 }
 float prevLat() {
return waypoints[index - 1].lat;
 }
 float prevLon() {
return waypoints[index - 1].lon;
 }
 void add(float x,float y) {
  waypoints[index].lat = x;
  waypoints[index].lon = y;
  increment();
 }
 void setIndex(int val) {
  index = val;
 }
 void increment() {
  if (index != MAX) {
index++;
  }
  else{
Serial &--#60;&--#60; "Overflow" &--#60;&--#60; endl;
  }
 }

 float next() {
 }
 int getIndex() {
  return index;
 }
} waypoint;

 

Endret av weebl
Lenke til kommentar
Videoannonse
Annonse

Kjører på en mikrokontroller (arduino) og såvidt jeg vet så vil std vector kreve mere resurser også? (som jeg ikke har stort av)pluss at jeg ikke lærer noe nytt av å bruke en vektor heller :p

 

Nå kan ikke jeg så mye om arduino, men klassen din allokerer minne til MAX koordinater + 4 byte for int index. Så hvis MAX=10 så beslagelegger klassen din 84 bytes selv om det bare er 2 koordinater. En vector (tar utgangspunkt i gcc 4.7 her kompilert med 32 bit) tar 12 bytes uten koordinater. Hvert koordinat i vectoren tar også 12 bytes (8 til koordinatet og 4 bytes for pekeren). Så dersom du har mindre enn 6 koordinater (underforstått at MAX=10) vil vectoren bruke mindre minne enn din klasse. For hvert koordinat over 6 vil vectoren ta 4 bytes mer for hvert koordinat enn hva din klasse gjør.

 

At man vil lære seg noe nytt er jo selvfølgelig helt supert, men det lukter litt "Not invented here" syndromet, og man bør så absolutt benytte seg av biblioteker slik at man kan konsentrere seg om å lage funksjonaliteten i programvaren i steden for å finne opp hjulet på ny for hver gang.

 

Du er selvfølgelig den eneste som vet hvor kritisk det er å spare 4 bytes pr. koordinat siden vi ikke vet hvor mye minne du har tilgjengelig og hva andre ting du har tenkt å implementere, men jeg vil sterkt anbefale deg å benytte deg av c++ standard library dersom mulig, siden du da benytter kode som er mye testet og andre c++ utviklere vil lettere kunne lese koden.

Lenke til kommentar

Ser ut som om det bare er å bruke STL da :)

 

Er liksom litt tricky med mikrokontrollere da biblioteker kan være mer effektivt, men det kan også være mindre effektivt. og når man har 2k ram og 30k til å lagre hele programmet på så må man passe på litt.

 

Når det kommer til dynamisk minneallokering så er dette litt bob-bob da man har såpass lite ram og det ikke returneres noen feilmelding på noe vis om man går tom for ledig minne.

Endret av weebl
Lenke til kommentar

Min erfaring er at STL + microkontrollere kan gå dårlig sammen, men da rett og slett pga. umoden C++-kompilator, noe som nok dessverre fortsatt er et høyst reelt problem. Jeg var iallfall med på å brenne oss hardt på akkurat det der i et prosjekt med MSP430 for ca 1,5 år siden. En feil i kompilator medførte økende bruk av flash i takt med antall kall mot samme funksjon i en STL-klasse.

 

Det sagt så er det ingenting galt i å prøve ut STL. oelbox har helt rett i at det ikke er noe alarmerende mye høyere minnebruk. Det som nok kan være veldig risky er minnefragmentering pga. dynamisk allokering. Det er helt og holdent avhengig av hvordan du programmerer, hvor mye minne du faktisk bruker og når dynamisk allokert minne blir frigjort igjen (spesielt i forhold til minne som blir allokert i mellomtiden). Frigjøres allokert minne i motsatt rekkefølge av allokeringen vil det f.eks. være helt uproblematisk å allokere minne dynamisk.

 

Generelt ville jeg nok gjort minst mulig dynamisk allokering, bare for sikkerhetsskyld. Du er inne på det selv. Det er rimelig komplisert å nøste opp akkurat den typen problemer hvis det inntreffer.

Lenke til kommentar

Uansett ser det ut som du skriver C.

 

Kanskje det kan være en idé å benytte templates for å bestemme størrelsen?

 

struct coord
{
 float lat;
 float lon;
};
template<int MAX> class waypoints
{
private:
 coord waypoints[MAX];
 int index;
public:
 coord& current() const
 {
       return waypoints[index];
 }
 coord& next() const
 {
       return waypoints[index + 1];
 }
 coord& prev const()
 {
       return waypoints[index - 1];
 }
 float prevLon()
 {
    return waypoints[index - 1].lon;
 }
 void add(float x,float y) {
  waypoints[index].lat = x;
  waypoints[index].lon = y;
  increment();
 }
 void setIndex(int val) {
  index = val;
 }
 void increment()
 {
  if (index < MAX)
    index++;
  else
       Serial &--#60;&--#60; "Overflow" &--#60;&--#60; endl;
 }
 const int getIndex()
 {
  return index;
 }
} waypoint;

Lenke til kommentar

Folka som lager kompilatoren til Arduino har røyka mormors gamle ullsokker, men på en god dag. De benytter gcc, kompilatoren som brukes til nesten alt i Linux. Det er en god kompilator, og du trenger ikke å forvente deg for mye tull.

 

Når det er sagt, så har de jo røyka disse gamle ullsokkene, og tatt vekk endel features fordi de var redd for at noen skulle skyte seg selv i beinet. Jeg skjønner at å kunne kjøre new på en stor array er problematisk på en microkontroller, men om jeg vil gjør det så burde jeg få lov. Det kunne jo hende at noen som vet hva de driver med faktisk ville prøve seg.

 

Med det sagt, ja, STL vil slite litt, mye på grunn at at de har valgt å fjerne new/delete og new[]/delete[]. De to første kan du få inn igjen ved å importere new.h i arduino IDE, men de to siste fikk jeg aldri til å spille, så jeg måtte lage en wrapper klasse til mitt bruk.

 

Som nevnt over så bruker du unødvendig mye minne på dette. Implementer et objekt som holder orden på en linket liste ( funksjonalitet som STL sin list&--#60;&--#62; ). Vektor bruker litt mindre minne per objekt, men kan aldri bruke mer enn 50% av RAM, for mer enn det gjør det umulig med minneutvidelse (si du legger inn nytt objekt, og den må reallokere og flytte data). Linket liste er det du vil ha her tror jeg.

 

For å returnere to objekter/verdier så kan du bruke stl::pair&--#60;&--#62;, eller la funksjonen ta imot to referanser:

 

void tulleFunksjon( int &a, int &b )
{
 a = 2; b = 3; //jobber direkte på variablene som ble sendt med, ikke en intern kopi
}

int main( int argc, char **argv )
{
 int a = 0; int b = 0;
 tulleFunksjon( a, b );
 printf( "%d %d\n", a, b ); // Evt std::cout &--#60;&--#60; a &--#60;&--#60; " " &--#60;&--#60; b &--#60;&--#60; std::endl;
 return 0;
}

// output: "2 3"

 

Jeg foretrekker ofte pair, men på små microkontrollere som dette så bruker jeg referanse. Mye mer effektivt, og ikke noe minne-allokering og kopiering ved funksjonskall og evt. retur.

 

-Ko_deZ-

Endret av Ko_deZ
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...