Как удалить 2D вектор указателей на объекты без утечки памяти? C ++ и SFML

У меня есть 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()

Если потребуется какой-либо дополнительный код, пожалуйста, дайте мне знать, спасибо.

1

Решение

Судя по Tile класс, кажется, глупо использовать Tile указатели вместо непосредственного использования Tileв вашем векторе. Вот возможное решение вашей проблемы:

  1. Определите конструктор копирования, то есть определите, что Tile::Tile(const Tile&) должен сделать (он должен скопировать все элементы данных во вновь созданную плитку).
  2. Определить оператор присваивания, то есть определить, что 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> >

вместо.

1

Другие решения