Динамически распределяемый массив объектов - PullRequest
1 голос
/ 29 февраля 2012

Мне нужен двойной указатель типа DizzyCreature (мой класс), чтобы указывать на массив указателей DizzyCreature. Когда я запускаю его, я получаю «Место чтения нарушения доступа 0x ...». Я могу создать DizzyCreature * и просто вызывать его функции-члены, но когда не могу запустить массив и сделать то же самое для каждого объекта.

Я следую этим инструкциям: http://www.cplusplus.com/forum/beginner/10377/

код

server.h:

class Server
{
 public:
  Server(int x, int y, int count);
  ~Server(void);

  void tick();


 private:
  DizzyCreature** dcArrPtr;
  DizzyCreature* dcPtr;

  int _count;
};

server.cpp:

Server::Server(int x, int y, int count)
{
  dcPtr = new DizzyCreature[count];       // this works just fine

  dcArrPtr = new DizzyCreature*[count];   // this doesn't (but gets past this line)
  _count = count;
}

Server::~Server(void)
{
  delete[] *dcArrPtr;
  delete[] dcPtr;
}

void Server::tick()
{
  dcPtr->takeTurn();                // just fine

  for (int i = 0; i < _count; i++) {
    dcArrPtr[i]->takeTurn();        // crash and burn
  }
}

EDIT: Функция-член takeTurn () находится в родительском классе DizzyCreature. Программа превращает его в функцию, но как только она пытается изменить закрытую переменную-член, возникает исключение. Если это имеет значение, DizzyCreature относится к типу GameCreature и WhirlyB, поскольку это назначение для MI.

Ответы [ 6 ]

2 голосов
/ 29 февраля 2012

Вы выделили пространство для dcArrPtr, но не выделяли каждый объект в этом массиве. Вы должны сделать следующее:

Server::Server(int x, int y, int count)
{
  dcPtr = new DizzyCreature[count];

  dcArrPtr = new DizzyCreature*[count];
  for ( int i = 0; i < count; i++ ) {
    dcArrPtr[ i ] = new DizzyCreature;
  }
  _count = count;
}

Server::~Server(void)
{
  for ( int i = 0; i < count; i++ ) {
    delete dcArrPtr[ i ];
  }
  delete[] *dcArrPtr;
  delete[] dcPtr;
}
1 голос
/ 29 февраля 2012

Это:

dcPtr = new DizzyCreature[count];       

"создает" массив DizzyCreature с, тогда как:

dcArrPtr = new DizzyCreature*[count];

"создает" массив из указателей * от 1009 * до DizzyCreature с, но принципиально не создает экземпляры, на которые указатели могут указывать. В любом случае, предпочтительным решением является использование стандартного контейнера для подобных задач. Если вы действительно хотите сделать это так (и понимаете, что делать это вручную не рекомендуется), вам понадобится цикл для вызова new для элемента управления в массиве указателей.

0 голосов
/ 29 февраля 2012

Если бы вы видели реализацию динамического выделения памяти 2-мерного массива. Это дало бы вам лучшее представление о том, как действовать в таких случаях. Большинство ответов уже ответили вам, что делать. Но просто перейдите по любой ссылке и посмотрите, как распределяется память в случае двумерного массива. Это также поможет вам.

0 голосов
/ 29 февраля 2012

Вы выделяете массив указателей, но эти указатели недействительны, пока вы не установите для них что-либо.вместо этого используйте std::array и std::vector:

class Server
{
 public:
  Server(int x, int y, int count);

  void tick();


 private:
  std::vector<std::vector<DizzyCreature>> dcArrPtr;
  std::vector<DizzyCreature> dcPtr;


};

Server::Server(int x, int y, int count)
{
  dcPtr.resize(count);

  dcArrPtr.resize(count);
}



void Server::tick()
{
  dcPtr[0].takeTurn();

  for (int i = 0; i < dcArrPtr.size(); i++) {
    dcArrPtr[i][0].takeTurn();
  }
}
0 голосов
/ 29 февраля 2012

Вы выделяете массив указателей подсчета вместо массива объектов подсчета.

Вместо

dcArrPtr = new DizzyCreature*[count];

вам может потребоваться

dcArrPtr = new DizzyCreature[count];
0 голосов
/ 29 февраля 2012

Используйте

std::vector<std::vector<DizzyCreature>>

Кроме того, если вы хотите использовать необработанные указатели (которые я не рекомендую), вам придется выделить память для каждого указателя в вашем массиве.

class A
{
    std::vector<std::vector<int>> v_;
public:
    A()
        : v_(500, std::vector<int>(500))
    {} // 500 x 500
};

class B
{
    int** v_;
public:
    B()
        : v_(new int*[500])
    { // not even exception safe
        for (int i = 500; i--; )
            v_[i] = new int[500];
    }
    ~B()
    {
        for (int i = 500; i--; )
            delete[] v_[i];
        delete[] v_;
    }
};
...