Avatar billede tangveje Nybegynder
25. september 2004 - 22:48 Der er 15 kommentarer og
1 løsning

Allokering af hukommelse i klasse

Hey... er igang med et klassisk 'kryds og bolle' spil, for at udvikle mine ikke alt for gode C++ evner :) Jeg har allerede et funktionelt spil, men koden er langt fra køn, så jeg bestemte mig for at experimentere lidt med andre måder at gøre tingene på. Desværre er jeg løbet ind i et problem...

Jeg vil gerne gøre det muligt for spilleren at kunne bestemme brættets størrelse hver gang de starter et nyt spil. Jeg bruger et array til at representere brættet, og vil derfor gerne kunne ændre 'størrelsen' af det array dynamisk. Her er min hurtige test kode.

#include <cstdio>
#include <cstdlib>

using namespace std ;

class game
{
    public:
    void SetBoardSize( int nSize ) ;
   
    private:
    int *board ;
} ;

void game::SetBoardSize( int nSize )
{
    board = new int[nSize][nSize] ;
}

int main( )
{
    return 0 ;
}

Tag jer ikke af at den ser meget ufærdig ud :) Når jeg forsøger at compile denne kode, får jeg følgende fejl (bruger GCC under Linux).

main.cpp: I member function 'void game::SetBoardSize(int)':
main.cpp:17: error: cannot convert `int (*)[((nSize - 1) + 1)]' to `int*' in assignment

Hvad er problemet? Prøvede at søge på google, men fandt kun et spm fra en anden med præcist samme problem, men intet svar. Skal siges at det er første gang jeg bruger 'new' så det er ganske muligt det bare er en eller anden latterlig begynder fejl :)

Og et halvt relateret spm... hvornår præcist udføres en klasses destructor? Jeg vil gerne placere den tilhørende 'delete' i klassens destructor, men er usikker på hvornår det så bliver udført.
Avatar billede arne_v Ekspert
25. september 2004 - 22:49 #1
Dynamisk allokering af 2 dimensionelle arrays er et problem !
Avatar billede arne_v Ekspert
25. september 2004 - 22:50 #2
Men der findes forskellige workarounds. Jeg har et eksempel.
Avatar billede arne_v Ekspert
25. september 2004 - 22:54 #3
#include <iostream>

using namespace std;

void init1(int *a,int n,int m)
{
  for(int i=0; i<n; i++) for(int j=0; j<m; j++) a[i*m+j]=1;
  return;
}

void show1(int *a,int n,int m)
{
  for(int i=0; i<n; i++) {
      for(int j=0; j<m; j++) cout << " " << a[i*m+j];
      cout << endl;
  }
  return;
}

void init2(int **b,int n,int m)
{
  for(int i=0; i<n; i++) for(int j=0; j<m; j++) b[i][j]=2;
  return;
}

void show2(int **b,int n,int m)
{
  for(int i=0; i<n; i++) {
      for(int j=0; j<m; j++) cout << " " << b[i][j];
      cout << endl;
  }
  return;
}

typedef int twodim[][3]; // <-------- fixed second dimension

void init3(twodim c,int n,int m)
{
  for(int i=0; i<n; i++) for(int j=0; j<m; j++) c[i][j]=3;
  return;
}

void show3(twodim c,int n,int m)
{
  for(int i=0; i<n; i++) {
      for(int j=0; j<m; j++) cout << " " << c[i][j];
      cout << endl;
  }
  return;
}

int main()
{
  int n = 2;
  int m = 3;
  int *a = new int[n*m];
  init1(a,n,m);
  show1(a,n,m);
  int **b = new (int *)[n];
  for(int i=0; i<n; i++) b[i]=new int[m];
  init2(b,n,m);
  show2(b,n,m);
  twodim *c = new twodim[2];
  init3(*c,n,m);
  show3(*c,n,m);
}
Avatar billede arne_v Ekspert
25. september 2004 - 22:55 #4
#1 = simulation af 2D array via 1D array
#2 = array af array
#3 = fusker trick som jeg ikke engang er sikker på virke med alle compilere (men g++ æder den)
Avatar billede tangveje Nybegynder
25. september 2004 - 23:09 #5
Interresant, den skal jeg lige tygge lidt på tror jeg :)

Tænker lidt på om der kunne være andre måder at opnå samme resultat... måske slet ikke bruge et 2D array, men måske noget tilsvarende. Kan ikke lige komme på hvad det skulle være, men man ved jo aldrig.
Avatar billede bertelbrander Novice
25. september 2004 - 23:15 #6
Man kan også bruge en std::vector< std::vector<int > >
Avatar billede arne_v Ekspert
25. september 2004 - 23:18 #7
vector af vector, list af list etc. er vel nærmest variationer over array af array.
Avatar billede arne_v Ekspert
25. september 2004 - 23:19 #8
Men det har jeg også et lille eksempel på:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
  // 2 D array
  int a1[3][3];
  for(int i=0;i<3;i++) for(int j=0;j<3;j++) a1[i][j]=i*3+j+1;
  int *x1;
  x1 = a1[1];
  for(int i=0;i<3;i++) cout << " " << x1[i];
  cout << endl;
  // array af arrays
  int **a2 = new (int *)[3];
  for(int i=0;i<3;i++) a2[i]=new int[3];
  for(int i=0;i<3;i++) for(int j=0;j<3;j++) a2[i][j]=i*3+j+1;
  int *x2;
  x2 = a2[1];
  for(int i=0;i<3;i++) cout << " " << x2[i];
  cout << endl;
  // vector af vector
  vector< vector<int> > a3;
  vector<int> v[3];
  for(int i=0;i<3;i++)
  {
      for(int j=0;j<3;j++) v[i].push_back(i*3+j+1);
      a3.push_back(v[i]);
  }
  vector<int> x3 = a3[1];
  for(int i=0;i<3;i++) cout << " " << x3[i];
  cout << endl;
  return 0;
}
Avatar billede tangveje Nybegynder
25. september 2004 - 23:27 #9
Hmm, der var den igen... vektor :) Jeg synes hele tiden jeg finder adskillige forskellige definitioner af hvad en vektor er, burde nok snart tage mig sammen og få ordentlig styr på det.

Indtil da tror jeg jeg holder mig til arrays :) Men tak for eksemplerne, vil prøve at lege lidt frem og tilbage, og se hvad der føles bedst. Lægger du et svar arne?
Avatar billede arne_v Ekspert
25. september 2004 - 23:37 #10
En vector er et "totalt dynamisk array".

int a[10]; // statisk = størrelse bestemt på compile time
int *a = new int[10]; // dynamisk = størrelse bestemt på runtime, men fast efter new
vector<int> a; // total dynamisk = udvides hele tiden automatisk efter behov
Avatar billede tangveje Nybegynder
25. september 2004 - 23:43 #11
"men fast efter new", vil det sige jeg kun kan "forstørre" det én gang? I så fald vil det jo alligevel ikke være optimalt i dette tilfælde. Så skal jeg enten bruge en vektor, eller fastsætte mit array til den maximale størrelse og kun bruge en del af det. Har jeg ret?
Avatar billede arne_v Ekspert
25. september 2004 - 23:48 #12
I rigtigt mange tilfælde kender du den præcise størrelse når du laver new.

Men hvis ikke du gør det så er vector en god løsning.

Alternativerne er enten som du skriver at allokere en max. størrelse (og så
er det sjove ligesom gået af det dynamiske) eller at allokere N og når
man så skal bruge mere så allokerer man et nyt array N+N og kopierer
alt data fra det første til det nye og frigiver det første (og det er
lidt bøvlet).
Avatar billede tangveje Nybegynder
25. september 2004 - 23:59 #13
Hmm, ja det kan hurtigt gå hen og blive rigtigt bøvlet, specielt for sådan et simpelt spil :)

Jeg tror ind til videre jeg vil bruge et statisk array, og så kan jeg jo altid udskifte det med en vector eller noget andet senere. Sommetider er det bedst at få skidtet til at virke først, og så gå i dybden med detaljerne bagefter :) Men tak for hjælpen, nu har jeg lidt at spekulere over mens jeg koder videre.
Avatar billede tangveje Nybegynder
26. september 2004 - 16:57 #14
Så tror jeg endelig jeg fandt en optimal løsning. Har valgt at bruge vectors, og efter lidt søgning på google fandt jeg en smart kode så jeg nu kan arbejde med min "2D vector" som var den et dynamisk 2D array. Tilsyneladende bliver det ikke meget bedre :)

Her er min hurtige test kode

class board
{
    public:
        // Constructor
        board( ) { }
     
        board( int row, int col ) : vBoard( row )
        {
            for( int i = 0 ; i < row ; i++ )
        {
                vBoard[i].resize( col, 0 ) ;
            }
        }
     
        // Destructor
     
        // Accessors
        const vector<int>& operator[](int row) const ;
   
    void Assign( int x, int y, int val )
    {
        vBoard[x][y] = val ;
    }
   
    int Get( int x, int y )
    {
        return vBoard[x][y] ;
    }
           
        // Mutators 
    private:       
        vector< vector<int> > vBoard ;
} ;

int main( )
{
    board b( 3, 3 ) ;
   
    b.Assign( 2, 3, 4 ) ;
   
    printf( "2,3 : %d\n", b.Get( 2, 3 ) ) ;
    printf( "0,0 : %d\n", b.Get( 0, 0 ) ) ;
    printf( "0,2 : %d\n", b.Get( 0, 2 ) ) ;
   
    return 0 ;
}

Men tak for hjælpen, håber jeg selv kan klare den herfra :) Lægger du et svar, så vi kan få lukket?
Avatar billede arne_v Ekspert
26. september 2004 - 17:00 #15
kommer her
Avatar billede tangveje Nybegynder
26. september 2004 - 17:03 #16
Og værsgo :) Tak for hjælpen endnu en gang
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester