Давайте рассмотрим каждый фрагмент кода.
1) Выделение памяти
Tile* tile = new Tile();
Это создает новый объект Tile в куче и сохраняет адрес памятив переменной плитки.Имейте в виду, что переменная плитка - это только указатель, а не сам объект.
2) Копирование ссылки
void Level::addTile(int x, int y, Tile *tile) { map[x][y] = tile;}
Приведенная выше функция просто берет указательи сохраняет его в многомерный массив для будущего использования.В контексте всего перечисленного кода теперь будет две ссылки на объект ... плитку * в исходной вызывающей функции и запись в многомерном массиве.Опять же, имейте в виду, что это указатели (всего 4 байта, в зависимости от архитектуры вашей системы).
3) Установка указателя на NULL
tile = NULL;
Результатом этого кода является то, что плитка переменной указателя больше не будет указывать на созданный объект в куче.Однако объект все еще будет существовать.На данный момент, в контексте всего кода, у вас все еще будет указатель на объект из-за массива map [] [].
В действительности вам не нужна эта строка кода.плитка не является висящим указателем, так как она указывает на действительный объект (до того, как вы установите его в NULL).Код также не разрушает объект.Поскольку плитка является локальной переменной, она будет очищена при выходе из области действия функции.Будет очищен только указатель, а не объект, на который он указывает.Установка этого значения в NULL в этом сценарии очень мало, кроме циклов траты.
Это также не утечка памяти, скажем так.У вас все еще есть действительный указатель на объект в массиве map [] [], поэтому вы всегда можете использовать эту ссылку для очистки памяти.
4) Что нужно сделать
Вам необходимо удалить объект где-нибудь.В C ++ это ключевое слово delete.
delete tile;
ИЛИ
delete map[x][y];
Теперь имейте в виду, что после запуска приведенного выше кода память в куче будет освобождена обратно воперационная система и ваше приложение больше не могут безопасно обращаться к памяти.Следовательно, любой вызов map [x] [y] -> {SomeMethod} приведет к исключению нарушения прав доступа.Указатель, хранящийся в карте [x] [y], теперь является висящим указателем (он указывает на адрес памяти, недопустимый для этого типа).
Если вам нужно удалить плитку из карты уровня передвы уничтожаете уровень, вы делаете это:
void Level::deleteTile(int x, int y)
{
if (map[x][y] != NULL)
{
delete map[x][y];
map[x][y] = NULL;
}
}
Я бы также изменил метод addTile на что-то вроде этого:
void Level::addTile(int x, int y, Tile *tile)
{
deleteTile(x, y);
map[x][y] = tile;
}
Наконец, когда вы уничтожаете объект уровня,вам нужно сделать что-то вроде этого:
void ~Level()
{
for (int i; i<MaxX; i++)
{
for (int j; j<MaxY; j++)
{
delete map[i][j];
}
}
}
Когда вы создаете объект уровня, вы должны обнулить массив map [] [], чтобы все значения также были равны NULL.Поскольку массив карт не является локальным для функции, рекомендуется установить для всех его значений указателя значение NULL, чтобы вы знали, когда он содержит действительный указатель, а когда - нет.
Если выдинамически создавайте (используя новое ключевое слово) массив map [] [], вам также нужно будет очистить его память, используя ключевое слово delete.
Надеюсь, это поможет.