У меня есть 2D вектор указателей плитки. Каждый раз, когда я загружаю другую карту, я хотел бы удалить все плитки в векторе, освобождая память, а затем снова заполнить ее разными плитками.
std::vector<std::vector<Tile*>> map;
Вот мой класс плитки:
#ifndef _TILE_H
#define _TILE_H
#include <SFML\Graphics.hpp>
class Tile
{
public:
int type;
int color;
int light_level;
int loc_x, loc_y;
Tile();
~Tile();
sf::Sprite baseSprite;
void Draw(int x, int y, sf::RenderWindow* rw);
void setTexture(sf::Texture& texture);
};
#endif
Я заполняю векторы вот так:
map[x][y] = tile;
Проблема в том, что каждый раз, когда я добавляю векторы с Tiles, моя память продолжает заполняться, пока игра не вылетает. У меня вопрос, как я могу правильно удалить все из векторов, чтобы освободить память?
Вот моя попытка удалить плитки, которые не освободили память:
for(int ii = 0; ii < this->map.size(); ii++){
for(int jj = 0; jj < this->h; jj++){
delete &this->map[ii][jj]->baseSprite;
delete &this->map[ii][jj]->color;
delete &this->map[ii][jj]->light_level;
delete &this->map[ii][jj]->loc_x;
delete &this->map[ii][jj]->loc_y;
delete &this->map[ii][jj]->type;
delete &this->map[ii][jj];
}
}map.clear()
Если потребуется какой-либо дополнительный код, пожалуйста, дайте мне знать, спасибо.
Судя по Tile
класс, кажется, глупо использовать Tile
указатели вместо непосредственного использования Tile
в вашем векторе. Вот возможное решение вашей проблемы:
Tile::Tile(const Tile&)
должен сделать (он должен скопировать все элементы данных во вновь созданную плитку).Tile& Tile::operator=(const Tile&)
должен сделать (это должно вызвать все operator=
функционирует на всех своих членах данных и return *this
).На первый взгляд это кажется нормальным, но я посмотрел на sf::Sprite
документация, и ни конструктор копирования, ни оператор присваивания не определены для sf::Sprite
, Кажется, спрайты могут быть созданы только через sf::Texture
, К счастью, каждый sf::Sprite
предоставляет публичную функцию-член, которая возвращает свою собственную границу sf::Texture
, Тем не менее, глядя на документацию sf::Sprite::getTexture()
, он возвращает указатель для sf::Texture
что может быть NULL
если никакая текстура еще не связана с sf::Sprite
, Вы должны проверить это в конструкторе копирования и операторе присваивания для Tile
,
Конструктор копирования должен выглядеть примерно так:
Tile::Tile(const Tile& other)
: type(other.type)
, color(other.color)
, light_level(other.light_level)
, loc_x(other.loc_x)
, loc_y(other.loc_y)
, baseSprite()
{
sf::Texture* result = other.baseSprite.getTexture();
if (result)
{
baseSprite.setTexture(*result);
}
}
и оператор присваивания должен выглядеть примерно так:
Tile& Tile::operator = (const Tile& other)
{
type = other.type;
color = other.color;
light_level = other.light_level;
loc_x = other.loc_x;
loc_y = other.loc_y;
sf::Texture* result = other.baseSprite.getTexture();
if (result)
{
baseSprite.setTexture(*result);
}
return *this;
}
Там больше, чем это, хотя, кажется, sf::Sprite
также может быть определен под прямоугольником текстуры, и он, вероятно, имеет больше свойств, о которых нужно позаботиться. Например, sf::Sprite
также есть геттеры и сеттеры для его положения, поворота, глобального цвета, все, что вам нужно скопировать. В любом случае, как только это будет сделано, вы можете забыть о беспорядке указателя и создать экземпляр
std::vector<std::vector<Tile> >
вместо.