自动 object 更改内存位置

Automatic object changes memory location

对于初学者,让我们考虑一下我目前正在从事的项目的以下摘要。这是 header:

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 object sh 将指向一定数量模型的指针存储在向量 vector<Model*> models 中。这些模型可以使用 RenderModels 方法渲染。 在初始化期间,GUI 通过 quad 的地址 &quadquad 添加到 sh.models。然后方法DrawGUI可以用来缩放quad并绘制到屏幕上。

问题:

在我的主函数中使用DrawGUI时,缩放没有效果!

这是由于 "mysterious" 我希望有人能为我解开的行为。我已经知道问题的根源,但我无法掌握其背后的原因。 虽然SetScale函数修改了quad的维度,但这并不影响渲染,因为(我调试时验证过)&quadsh.models[0]在[=时有不同的值23=] 被调用。特别是,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 更改其地址?

根据最新的评论,问题已经很清楚了。 OP 的代码中存在以下行:

GUI gui = GUI().Initialize();

Initialize最重要的部分是:

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

因此,调用了 GUI 对象的复制构造函数。在没有任何用户提供的代码的情况下,使用默认的复制构造函数——并且由于 OP 还提到了指针,这些指针被复制为默认复制构造函数的一部分。但是没有人复制这些对象!事实上,没有人在新对象上调用 Initialize

给出的片段中的解决方案并不明确,但有几件事是显而易见的:

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