2016-06-05 9 views
-1

Для начала рассмотрим следующий абстракт из проекта, над которым я сейчас работаю. Вот заголовок:Автоматическое изменение местоположения памяти объекта

class GUI { 
public: 
    GUI& Initialize(); 
    void DrawGUI(float width, float height); 

private: 
    Model quad; 
    Shader sh; 
    Camera cam; 
}; 

Хотя это файл CPP:

GUI& GUI::Initialize() { 
    quad.Initialize().LoadModel("Resources/quad.obj"); 
    sh = Shader().Initiliaze(); 
    sh.models.push_back(&quad); 
    return *this; 
} 

void GUI::DrawGUI(float width, float height) { 
    quad.SetScale(width, height, 0); 
    sh.RenderModels(); 
} 

Прежде чем перейти непосредственно к проблеме объяснения связано. Объект Shadersh хранит указатели на определенное количество моделей в векторе vector<Model*> models. Эти модели могут быть визуализированы с использованием метода RenderModels. Во время инициализации GUI добавляет quad в sh.models через адрес quad&quad. Затем способ DrawGUI может использоваться для масштабирования quad и для его рисования на экране.

Проблема:

При использовании DrawGUI в моей основной функции, масштабирование не имеет никакого эффекта!

Это связано с «таинственным» поведением, которое я надеялся, что кто-то может разгадать меня. Я уже знаю корень проблемы, но я не могу понять, что стоит за ней. Функция SetScale изменяет размеры quad, это не влияет на рендеринг, так как (я проверил это при отладке) &quad и sh.models[0] имеют разные значения, когда вызывается DrawGUI. В частности, quad меняет свой адрес без какого-либо вмешательства с моей стороны в одну точку между инициализацией и вызовом вызова. Небольшое изменение устраняет проблему и масштабирование происходит:

void GUI::DrawGUI(float width, float height) { 
    sh.models[0].SetScale(width, height, 0); 
    sh.RenderModels(); 
} 

Но это не поможет мне понять, почему эта проблема возникает в первых местах. Все становится еще менее ясным из-за того, что, хотя проблема возникает, когда GUI объявляется с использованием автоматического хранилища, то есть GUI gui;, он не появляется, когда я выделяю GUI в куче. Фактически quad не меняет адрес, сохраняя его таким же, как sh.models[0], и все работает отлично.

Почему различное поведение между двумя типами распределения? Есть ли что-то в автоматическом распределении, которое мне не хватает? Почему quad сменить адрес?

+1

Если адрес «quad» таинственно изменяется, это говорит о том, что вы создаете новые объекты GUI, когда вы этого не ожидаете. Например. если вы 'push_back'' GUI' в контейнер, он создаст его копию. Вы не указали достаточно кода, чтобы узнать, действительно ли это так, но если вы поместите 'cout' в конструктор' GUI', вы должны с легкостью определить, что происходит. –

+0

Вы пытались использовать удаленный экземпляр копии? Я предполагаю, что у вас есть GUI, который передается как копия какой-то функции или что-то в этом роде. –

+0

@JonathanPotter Я просто попробовал трюк 'cout'. У меня есть только одна печать ... – Geoffrey91

ответ

2

С последними комментариями проблема теперь понятна. После строки существует в коде OP в:

GUI gui = GUI().Initialize(); 

И самая важная часть Initialize является:

GUI& GUI::Initialize() { 
    // ... 
    return *this; 
} 

В результате, копия-конструктор вызывается из объекта GUI. При отсутствии любого кода, предоставленного пользователем, используется конструктор-экземпляр по умолчанию - и, поскольку OP также упоминает указатели, эти указатели копируются как часть конструктора копии по умолчанию. Но никто не копирует эти объекты! На самом деле никто не звонил Initialize на новый объект.

Решение не ясно из приведенных отрывков, но несколько вещей очевидны:

  • Не используйте Initialize функцию. Используйте конструктор, для чего он нужен.
  • Осторожно подумайте о копировании своего объекта. Если вы сомневаетесь, удалите как конструктор копии, так и оператор присваивания.
  • Не используйте необработанные указатели для управления объектом, для чего нужны интеллектуальные указатели. Среди умных указателей ваш первый выбор должен быть unique_ptr.
+0

Хорошо, теперь я как бы понял ... Я постараюсь следовать вашим рекомендациям, спасибо! – Geoffrey91