Используя статический указатель на управление памятью класса? - PullRequest
2 голосов
/ 21 октября 2011

У меня есть класс для звезд в моей игре, я хочу, чтобы они использовали одну и ту же текстуру, поэтому я пришел с этим кодом ...

sf::Texture* Star::starTexture = NULL;
unsigned int Star::refCount = 0;

Star::Star() : starSpeed(0), starScale(0), locX(0), locY(0)
{
    if (starTexture == NULL)
    {
        starTexture = new sf::Texture();
    }

    refCount++;
}

Star::~Star()
{
    refCount--;

    if (refCount == 0)
    {
        delete starTexture;
        starTexture = NULL;
    }
}

Я использую класс звездэто ...

for (int i = 0; i < STAR_COUNT; ++i)
{
    Star star;

    star.Initialize(/* blah blah */);

    starVector.push_back(star);
}

Я новичок в "продвинутых методах c ++" и боюсь, что это не сработает.Нужно ли определять конструктор копирования?вектор испортит мой счетчик ссылок?Я открыт для предложений о лучшем способе сделать это тоже.Я думаю, я мог бы оставить текстуру вне класса и передать ссылку, когда я инициализирую каждую звезду, но я предпочитаю, чтобы текстура оставалась внутри класса ...

1 Ответ

5 голосов
/ 21 октября 2011

Да, все будет плохо, если вы явно не определите copy constructor и copy assignment operator для своего класса.

Контейнеры STL, такие как vector, имеют семантику копирования по значению .Когда объект Star копируется в vector, копируется необработанный указатель внутри него.Таким образом, теперь у вас есть несколько указателей, указывающих на одну память, что определенно позволяет вам в лучшем случае перейти к неопределенному поведению.

Что вам следует сделать, это определить эти функции явно.Вручную выполните глубокую копию этой памяти и правильно увеличьте счетчик ссылок.

Лучшим способом является удержание RAII-объекта, подобного boost::shared_ptr или std::tr1::shared_ptr, внутри вашего класса ион обрабатывает управление ресурсами (включая подсчет ссылок) автоматически для вас.Тогда вам больше не нужно явно определять эти функции.

class Star
{
..
private:
  std::tr1::shared_ptr<sf::Texture> m_starTexture;
};

// link the smart pointer w/ resource
Star::Star(): m_starTexture(new Texture())
{
  ...  
}

Это гарантированно будет работать с помощью функций языка:

  1. Когда ваш объект копируется, функции копированиянестатических объектов-членов называются .
  2. Когда ваш объект удаляется, деструкторы нестатических объектов-членов называются .

В этом случае функции копирования интеллектуального указателя будут правильно увеличивать refсчитать, в то время как его деструктор уменьшает счетчик ссылок и освобождает ресурс, если счетчик ссылок равен 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...