自动对象更改内存位置

时间:2016-06-05 01:47:26

标签: c++ memory-management raii temporary-objects

对于初学者,让我们考虑一下我目前正在进行的项目中的以下摘要。这是标题:

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();
}

在直接解决问题之前,需要解释。 Shader对象sh存储指向向量vector<Model*> models中特定数量模型的指针。可以使用RenderModels方法呈现这些模型。 在初始化期间,GUI通过quad的地址sh.modelsquad添加到&quad。然后,方法DrawGUI可用于缩放quad并在屏幕上绘制它。

问题:

在我的main函数中使用DrawGUI时,缩放无效!

这是由于一个神秘的&#34;我希望有人能为我解开的行为。我已经知道问题的根源,但我无法理解它背后的原因。 虽然SetScale函数会修改quad的维度,但这不会影响呈现,因为(我在调试时已对此进行了验证)&quadsh.models[0]在{{DrawGUI时具有不同的值1}}被调用。特别是,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 个答案:

答案 0 :(得分:2)

根据最新评论,现在问题很明显。 OP代码中存在以下行:

GUI gui = GUI().Initialize();

Initialize最重要的部分是:

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

结果,调用GUI对象的复制构造函数。如果没有任何用户提供的代码,则使用默认的复制构造函数 - 并且由于OP也提到指针,这些指针将作为默认复制构造函数的一部分进行复制。但没有人复制这些对象!事实上,没有人在新对象上调用Initialize

解决方案在给定的片段中并不清楚,但有几件事是显而易见的:

  • 不要使用Initialize功能。使用构造函数,它的用途是什么。
  • 仔细考虑复制你的对象。如有疑问,请删除复制构造函数和赋值运算符。
  • 不要使用原始指针来管理对象,这就是智能指针的用途。在智能指针中,您的首选应该是unique_ptr