У вас проблема здесь:
Player * Table::get_all_players()
{
return Players;
}
Вы возвращаете указатель (и владельца) на Poker_Game
, когда он вызывает эту функцию:
// One place you call it from.
set_current_players(table -> get_all_players());
Проблема в том, что два объекта теперь требуют владения Players
, и оба вызывают delete []
на имеющемся у них указателе.
Poker_Game::~Poker_Game()
{
delete[] Current_players;
}
Table::~Table()
{
delete[] Players;
}
Не говорю, что это ваша единственная ошибка.
Вы в основном попали в ловушку семантики плохого владения в вашем приложении. В C ++ мы решили эту проблему (в отличие от C), используя специальные типы и языковые конструкции для явного обозначения владельца. Таким образом, мы точно знаем, кому принадлежит объект и, следовательно, кто отвечает за его удаление.
Ваши проблемы можно легко решить, выполнив несколько действий.
- Не выделять динамически массивы.
Используйте std::vector<>
для управления выделением для вас.
- Не выделять объекты динамически, срок жизни которых не дольше, чем функция.
Просто используйте локальную переменную и позвольте правилам области видимости обработать ее.
- Если вам необходимо динамически выделить объект, используйте умный указатель.
std :: unique_ptr и std :: shared_ptr очень хорошо управляют памятью для выделенных объектов.
- Если вы передаете объект другому объекту (и не передаете права собственности), тогда передайте по ссылке (а не по указателю).
Это говорит другому классу, что они не владеют объектом и, следовательно, не должны его удалять.
Простое правило, которым следует жить, - это «Разделение проблем».
Класс должен быть либо бизнес-логикой, либо управлением ресурсами. Таким образом, ваш класс должен либо обрабатывать логику покера, либо они должны обрабатывать логику управления памятью, которую вы выделяете (не обе). Таким образом, любой класс, который обрабатывает покер, не должен вызывать новый / удалять класс, который обрабатывает новый / удалять, в нем не должно быть покерной логики.
Теперь стандартные библиотеки предоставляют много кода для управления ресурсами, поэтому вам не нужно, вы можете просто использовать существующий код и сосредоточиться на своей покерной логике. Если после того, как игра заработает, вы решите, что стандартное управление ресурсами недостаточно эффективно, и вы можете сосредоточиться на его обновлении как отдельной задаче.