Копия объекта или константный указатель?

0

Я сделал 2d игровой движок, но я сомневаюсь, что один из способов, который я сделал, это лучший способ сделать что-то структурно. Например, член Sprite может иметь несколько членов Graphic. Прямо сейчас я сохраняю эти элементы в vector<const Graphic*> (не std::vector, но я буду использовать это для простоты в примере):

class Sprite {
private:
    std::vector<const Graphic*> _graphicList;
public:
    Sprite();
    ~Sprite();
    void addGraphic(const Graphic* toAdd); //adds a const Graphic* to _graphicList
    void draw() const; //draws all items in _graphicList
};

Вышеприведенный пример отлично работает. Проблема в том, что мне нужно сохранить объект Graphic в области, чтобы это работало. Это приведет к ошибке:

void foo (bool redCircle) {
    Sprite sprCircle;
    if(redCircle) {
        Graphic gfxRedCircle("redCircle.bmp");
        sprCircle.addGraphic(&gfxRedCircle);
    }
    else {
        Graphic gfxBlueCircle("blueCircle.bmp");
        sprCircle.addGraphic(&gfxBlueCircle);
    }
    sprCircle.draw(); //would possibly not work, since the Graphic is out of scope
}

Я мог бы просто создавать копии:

class Sprite {
private:
    std::vector<Graphic> _graphicList;
public:
    Sprite();
    ~Sprite();
    void addGraphic(Graphic& toAdd); //adds a Graphic to _graphicList
    void draw() const; //draws all items in _graphicList
};

Однако это будет тратить драгоценную память, если я сохраню Графика в области.

Поэтому, наверное, мой вопрос сводится к следующему:
В игровом движке, что более важно: надежность или эффективное использование памяти?

  • 0
    Если вы беспокоитесь об использовании памяти, то зачем вам сначала создавать локальные копии? Почему бы не загрузить изображения один раз и глобально, а затем передать указатели на эти текстуры?
  • 0
    @remyable, это очень упрощенный пример. Фактическое изображение загружается только один раз, однако вы можете иметь много графических объектов, которые содержат указатель на фактическое изображение.
Теги:
class
pointers
game-engine

2 ответа

1
Лучший ответ

Если ваш объект выходит за пределы области видимости, любая попытка использовать его указателем или ссылкой имеет неопределенное поведение по стандарту языка C++ (что означает, что это может повредить какой-либо другой объект или может привести к сбою программы или убить вашу кошку больше всего ужасный путь). Поэтому не вопрос, должен ли объект быть в сфере действия - он должен быть!

Опять же, надежность - это качество, которое вы не хотите торговать ни за что. Если ваша программа выйдет из строя, пользователю все равно, как мало памяти она использует. Чтобы оптимизировать вашу программу в использовании памяти, вы должны внимательно рассмотреть множество факторов: где ваша программа использует большую часть памяти, как вы можете снизить это использование и какие трюки вы могли бы потянуть, чтобы снизить ваш объем памяти (например, путем кеширования и сильно повторное использование существующих объектов). Каждый из этих факторов сильно зависит от вашей конкретной программы, поэтому обсуждать ее в целом вряд ли полезно для вашей конкретной цели.

  • 0
    Я знаю, что это должно быть в объеме. //would possibly not work, since the Graphic is out of scope специально указывалось, что поведение не определено. Может показаться, что это работает, но это не гарантировано и не является хорошей практикой. Спасибо за ваши мнения. Это то, о чем я думал, но я хотел посоветоваться с кем-то еще, прежде чем вносить такие большие изменения в мою кодовую базу.
0

Правильность должна быть первым соображением. Использование объекта области видимости является неправильным, и ваша программа может прервать/повесить (неопределенное поведение).

Есть несколько способов, в зависимости от того, что вам нужно:

  • Скопировать объект

void addGraphic(const Graphic &toAdd);

Это может означать, что вам нужно внедрить операцию конструктора глубоких копий/копий, если объект Graphic содержит указатели, и вы хотите получить идеальный клон (не только ссылаясь на одну и ту же память). Если вы не делаете разворачивать копию, исходный объект может быть освобожден, и вы все равно ссылаетесь на освобожденную память.

  • Создайте объект самостоятельно
void addGraphic(const string &bmpName);

Просто создайте объект Graphic внутри addGraphic, а затем вставьте его в вектор, таким образом вы владеете объектом, он не будет недоступен.

  • 0
    Просто чтобы прояснить, я не использую объект вне области видимости. Но это может произойти, если кто-то еще изменит кодовую базу или даже если я вернусь к этому через год, чтобы исправить ошибки и забыть. Все объекты, которым требуется глубокая копия, уже имеют конструктор копирования. Не передать путь к файлу спрайту было сознательным выбором дизайна.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню