Я сделал 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
};
Однако это будет тратить драгоценную память, если я сохраню Графика в области.
Поэтому, наверное, мой вопрос сводится к следующему:
В игровом движке, что более важно: надежность или эффективное использование памяти?
Если ваш объект выходит за пределы области видимости, любая попытка использовать его указателем или ссылкой имеет неопределенное поведение по стандарту языка C++ (что означает, что это может повредить какой-либо другой объект или может привести к сбою программы или убить вашу кошку больше всего ужасный путь). Поэтому не вопрос, должен ли объект быть в сфере действия - он должен быть!
Опять же, надежность - это качество, которое вы не хотите торговать ни за что. Если ваша программа выйдет из строя, пользователю все равно, как мало памяти она использует. Чтобы оптимизировать вашу программу в использовании памяти, вы должны внимательно рассмотреть множество факторов: где ваша программа использует большую часть памяти, как вы можете снизить это использование и какие трюки вы могли бы потянуть, чтобы снизить ваш объем памяти (например, путем кеширования и сильно повторное использование существующих объектов). Каждый из этих факторов сильно зависит от вашей конкретной программы, поэтому обсуждать ее в целом вряд ли полезно для вашей конкретной цели.
//would possibly not work, since the Graphic is out of scope
специально указывалось, что поведение не определено. Может показаться, что это работает, но это не гарантировано и не является хорошей практикой. Спасибо за ваши мнения. Это то, о чем я думал, но я хотел посоветоваться с кем-то еще, прежде чем вносить такие большие изменения в мою кодовую базу.
Правильность должна быть первым соображением. Использование объекта области видимости является неправильным, и ваша программа может прервать/повесить (неопределенное поведение).
Есть несколько способов, в зависимости от того, что вам нужно:
void addGraphic(const Graphic &toAdd);
Это может означать, что вам нужно внедрить операцию конструктора глубоких копий/копий, если объект Graphic содержит указатели, и вы хотите получить идеальный клон (не только ссылаясь на одну и ту же память). Если вы не делаете разворачивать копию, исходный объект может быть освобожден, и вы все равно ссылаетесь на освобожденную память.
void addGraphic(const string &bmpName);
Просто создайте объект Graphic внутри addGraphic, а затем вставьте его в вектор, таким образом вы владеете объектом, он не будет недоступен.